home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 41 / Amiga Format CD41 (1999-06)(Future Publishing)(GB)[!][issue 1999-07].iso / -seriously_amiga- / programming / other / sounddt41src / dispatch.c < prev    next >
C/C++ Source or Header  |  1999-04-19  |  99KB  |  4,139 lines

  1.  
  2. /*
  3.  *  SoundDT41 -- A free release of the sound.datatype v41 source code
  4.  *  Copyright (C) 1998/99  Stephan Rupprecht
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  */
  21.  
  22. #ifndef __MAXON__
  23. #define  CLIB_ALIB_PROTOS_H
  24. #endif
  25.  
  26. #include <exec/memory.h>
  27. #include <exec/execbase.h>
  28. #include <dos/dos.h>
  29. #include <dos/var.h>
  30. #include <dos/dostags.h>
  31. #include <dos/rdargs.h>
  32. #include <graphics/gfx.h>
  33. #include <graphics/gfxbase.h>
  34. #include <datatypes/soundclass.h>
  35. #include <datatypes/soundclassext.h>
  36. #include <datatypes/datatypesclass.h>
  37. #include <datatypes/pictureclass.h>
  38. #include <libraries/iffparse.h>
  39. #include <devices/audio.h>
  40. #include <intuition/classes.h>
  41. #include <intuition/gadgetclass.h>
  42. #include <intuition/icclass.h>
  43. #include <intuition/imageclass.h>
  44. #include <intuition/intuitionbase.h>
  45. #include <devices/ahi.h>
  46. #include <gadgets/tapedeck.h>
  47. #include <graphics/gfxmacros.h>
  48. #include <graphics/gfxbase.h>
  49.  
  50. #ifdef __GNUC__
  51. #include <proto/dos.h>
  52. #include <proto/exec.h>
  53. #include <proto/iffparse.h>
  54. #include <proto/graphics.h>
  55. #include <proto/intuition.h>
  56. #include <proto/utility.h>
  57. #include <proto/datatypes.h>
  58. #include <proto/ahi.h>
  59. #else
  60. #include <pragma/exec_lib.h>
  61. #include <pragma/intuition_lib.h>
  62. #include <pragma/dos_lib.h>
  63. #include <pragma/utility_lib.h>
  64. #include <pragma/iffparse_lib.h>
  65. #include <pragma/graphics_lib.h>
  66. #include <pragma/datatypes_lib.h>
  67. #include <pragma/ahi_lib.h>
  68. #endif
  69.  
  70. #pragma header
  71.  
  72. #include "classbase.h"
  73. #ifndef __MAXON__
  74. #include "CompilerSpecific.h"
  75. #include "BoopsiStubs.h"
  76. #endif
  77. #include "aiff.h"
  78.  
  79. #ifndef __MAXON__
  80. #define IntuitionBase    cb->cb_IntuitionBase
  81. #define GfxBase        cb->cb_GfxBase
  82. #define DOSBase        cb->cb_DOSBase
  83. #define SysBase        cb->cb_SysBase
  84. #define DataTypesBase    cb->cb_DataTypesBase
  85. #define UtilityBase        cb->cb_UtilityBase
  86. #define IFFParseBase    cb->cb_IFFParseBase
  87. #else
  88. #define REG(r,v)    register __## r v
  89. #define __regargs
  90. #endif
  91.  
  92. #define G(x)                ((struct Gadget *)(x))
  93. #define MAX( a, b )            ((a) > (b) ? (a) : (b))
  94. #define EXTG( x )            ((struct ExtGadget *)(x))
  95.  
  96. #ifndef ID_CHAN
  97. #define ID_CHAN        MAKE_ID( 'C', 'H', 'A', 'N' )
  98. #endif
  99. #ifndef ID_16SV
  100. #define ID_16SV        MAKE_ID( '1', '6', 'S', 'V' )
  101. #endif
  102. #ifndef ID_PAN
  103. #define ID_PAN        MAKE_ID( 'P', 'A', 'N', ' ' )
  104. #endif
  105. #ifndef ID_ANNO
  106. #define ID_ANNO        MAKE_ID( 'A', 'N', 'N', 'O' )
  107. #endif
  108. #ifndef ID_AUTH
  109. #define ID_AUTH        MAKE_ID( 'A', 'U', 'T', 'H' )
  110. #endif
  111. #ifndef ID_FVER
  112. #define ID_FVER        MAKE_ID( 'F', 'V', 'E', 'R' )
  113. #endif
  114. #ifndef ID_Copyright
  115. #define ID_Copyright    MAKE_ID( '(', 'c', ')', ' ' )
  116. #endif
  117.  
  118. #define TEMPLATE    "VOLUME/N/K,BUFFERSIZE/N/K,AHI/S,AHIMODEID/K,FAM=FORCEAHIMODE/S,AMF=AHIMIXFREQ/N/K,AIFF16/S,C=COMPRESS/S," \
  119.                 "W=WIDTH/N/K,H=HEIGHT/N/K,BG=BACKGROUNDCOLOR/K,WF=WAVEFORMCOLOR/K,CP=CONTROLPANEL/T,NOGTSLIDER/S"
  120.  
  121. // MaxonC likes to use 16bit math even when 020+ optimiziation is turned on (BUG!)
  122. #ifdef __MAXON__
  123. #define UMult( x, y )    UMult32( (x), (y) )
  124. #define SMult( x, y )    SMult32( (x), (y) )
  125. #define UDiv( x, y )        UDivMod32( (x), (y) )
  126. #define SDiv( x, y )        SDivMod32( (x), (y) )
  127. #else
  128. #define UMult( x, y )    ( (x) * (y) )
  129. #define SMult( x, y )    ( (x) * (y) )
  130. #define UDiv( x, y )        ( (x) / (y) )
  131. #define SDiv( x, y )        ( (x) / (y) )
  132. #endif
  133.  
  134. #define Period2Freq( x )     ( UDiv( UMult( ((struct ExecBase *)SysBase)->ex_EClockFrequency, 5L ), (x) ) )
  135. #define Freq2Period( x )    Period2Freq( x )
  136. #define IsStereo( x )        ( (BOOL) ( ( x ) & 1 ) )
  137.  
  138. #ifndef SHRT_MAX
  139. #define SHRT_MAX    0x7fff
  140. #endif
  141.  
  142. #ifdef DEBUG
  143. #define dbug( x )    x
  144. #else
  145. #define dbug( x )
  146. #endif
  147.  
  148. /****************************************************************************/
  149.  
  150. ULONG Dispatch(REG(a0,Class *cl), REG(a2,Object *o), REG(a1,Msg msg));
  151. ULONG __regargs Sound_NEW( Class *cl, Object *o, struct opSet *ops );
  152. ULONG __regargs Sound_GET( Class *cl, Object *o, struct opGet *ops );
  153. ULONG __regargs Sound_SET( Class *cl, Object *o, struct opSet *ops );
  154. ULONG __regargs Sound_UPDATE( Class *cl, Object *o, struct opUpdate *opu );
  155. ULONG __regargs Sound_DISPOSE( Class *cl, Object *o, Msg msg );
  156. ULONG __regargs Sound_RENDER( Class *cl, Object *o, struct gpRender *gpr );
  157. ULONG __regargs Sound_HANDLEINPUT( Class *cl, Object *o, struct gpInput *gpi );
  158. ULONG __regargs Sound_TRIGGER( Class *cl, Object *o, struct dtTrigger *dtt );
  159. ULONG __regargs Sound_WRITE( Class *cl, Object *o, struct dtWrite *dtw );
  160. ULONG __regargs Sound_LAYOUT( Class *cl, Object *o, struct gpLayout *gpl );
  161. ULONG __regargs Sound_DOMAIN( Class *cl, Object *o, struct gpDomain *gpd );
  162. LONG __regargs Sound_SELECT( Class *cl, Object *o, struct dtSelect *dts );
  163. LONG __regargs Sound_CLEARSELECTED( Class *cl, Object *o, struct dtGeneral *dtg );
  164. ULONG __regargs Sound_HITTEST( Class *cl, Object *o, struct gpHitTest *gpht );
  165. ULONG __regargs Sound_GOINACTIVE( Class *cl, Object *o, struct gpGoInactive *gpgi );
  166. ULONG __regargs Sound_DRAW( Class *cl, Object *o, struct dtDraw *dtd );
  167. LONG __regargs Hex2Long( STRPTR hex );
  168. BOOL __regargs parsetaglist( Class *cl, Object *o, struct opSet *ops );
  169. struct Process * __regargs CreatePlayerProc( struct ClassBase *cb, struct MsgPort **mp );
  170. void __regargs GetSoundDTPrefs( struct ClassBase *cb );
  171. struct IBox __regargs GetAbsGadgetBox( struct IBox *domain, struct ExtGadget *g, BOOL useBounds );
  172. ULONG __regargs DoMemberHitTest( struct IBox *domain, Object *member, struct gpHitTest *gpht );
  173. void PlayerProc( void );
  174. void PlayerProcAHI( void );
  175. void __regargs makeqtab( BYTE *qtab );
  176. unsigned __regargs strlen( STRPTR str );
  177. ULONG propgdispatcher( REG(a0, Class *cl), REG(a2, Object *o), REG(a1, Msg msg) );
  178.  
  179. /****************************************************************************/
  180.  
  181. BYTE fibtab[] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
  182.  
  183. UBYTE bytesPerPoint[] = { 1, 2, 2, 4 };
  184.  
  185. LONG ifferr2doserr[] =
  186. {
  187.     0L,                        // EOF
  188.     0L,                                     // EOC
  189.     DTERROR_INVALID_DATA,    /* No lexical scope.                             */
  190.     ERROR_NO_FREE_STORE,    /* Insufficient memory.                          */
  191.     ERROR_SEEK_ERROR,        /* Stream read error.                            */
  192.     ERROR_SEEK_ERROR,        /* Stream write error.                           */
  193.     ERROR_SEEK_ERROR,        /* Stream seek error.                            */
  194.     DTERROR_INVALID_DATA,       /* File is corrupt.                              */
  195.     DTERROR_INVALID_DATA,       /* IFF syntax error.                             */
  196.     ERROR_OBJECT_WRONG_TYPE,/* Not an IFF file.                              */
  197.     ERROR_REQUIRED_ARG_MISSING,/* Required call-back hook missing.              */
  198.     0xDEADDEAD                      /* Return to client. You should never see this ! */
  199. };
  200.  
  201. struct DTMethod    TriggerMethods[] =
  202. {
  203.     "Play", "PLAY", STM_PLAY,
  204.     "Stop", "STOP", STM_STOP,
  205.     "Pause", "PAUSE", STM_PAUSE,
  206.     STM_DONE
  207. };
  208.  
  209. ULONG Methods[] = {
  210.     OM_NEW,
  211.     OM_DISPOSE,
  212.     OM_SET,
  213.     OM_GET,
  214.     OM_UPDATE,
  215.     GM_RENDER,
  216.     GM_LAYOUT,
  217.     GM_DOMAIN,
  218.     GM_HITTEST,
  219.     GM_HELPTEST,
  220.     GM_GOACTIVE,
  221.     GM_HANDLEINPUT,
  222.     GM_GOINACTIVE,
  223.     DTM_TRIGGER,
  224.     DTM_WRITE,
  225.     DTM_COPY,
  226.     DTM_SELECT,
  227.     DTM_CLEARSELECTED,
  228.     DTM_PROCLAYOUT,
  229.     DTM_REMOVEDTOBJECT,
  230.     DTM_OBTAINDRAWINFO,
  231.     DTM_DRAW,
  232.     DTM_RELEASEDRAWINFO,
  233.     ~0UL
  234. };
  235.  
  236. #ifdef __MAXON__
  237. struct Library            *AHIBase = NULL;
  238. #endif
  239.  
  240. /****************************************************************************/
  241.  
  242. ULONG Dispatch(REG(a0,Class *cl), REG(a2,Object *o), REG(a1,Msg msg))
  243. {
  244.     struct ClassBase *cb = (struct ClassBase *)cl->cl_UserData;
  245.     ULONG  retval;
  246.     
  247.     switch( msg->MethodID )
  248.     {
  249.         case OM_NEW:
  250.             retval = Sound_NEW( cl, o, (struct opSet *)msg );
  251.         break;
  252.  
  253.         case OM_GET:
  254.             retval = Sound_GET( cl, o, (struct opGet *)msg );
  255.         break;
  256.         
  257.         case OM_UPDATE:
  258.             retval = Sound_UPDATE( cl, o, (struct opUpdate *)msg );
  259.         break;
  260.  
  261.         case OM_SET:
  262.         case OM_NOTIFY:
  263.             retval = Sound_SET( cl, o, (struct opSet *)msg );
  264.         break;
  265.  
  266.         case OM_DISPOSE:
  267.             retval = Sound_DISPOSE( cl, o, msg );
  268.         break;
  269.         
  270.         case GM_HELPTEST:
  271.         case GM_HITTEST:
  272.             retval = Sound_HITTEST( cl, o, (struct gpHitTest *) msg );
  273.         break;
  274.  
  275.         case GM_GOACTIVE:
  276.         case GM_HANDLEINPUT:
  277.             retval = Sound_HANDLEINPUT( cl, o, (struct gpInput *)msg );
  278.         break;
  279.  
  280.         case GM_GOINACTIVE:
  281.             retval = Sound_GOINACTIVE( cl, o, (struct gpGoInactive *) msg );
  282.         break;
  283.  
  284.         case GM_DOMAIN:
  285.             retval = Sound_DOMAIN( cl, o, (struct gpDomain *)msg );
  286.         break;
  287.  
  288.         case GM_LAYOUT:
  289.         case DTM_PROCLAYOUT:
  290.             retval = Sound_LAYOUT( cl, o, (struct gpLayout *)msg );
  291.         break;
  292.  
  293.         case GM_RENDER:
  294.             retval = Sound_RENDER( cl, o, (struct gpRender *)msg );
  295.         break;
  296.  
  297.         case DTM_TRIGGER:
  298.             retval = Sound_TRIGGER( cl, o, (struct dtTrigger *)msg );
  299.         break;
  300.  
  301.         case DTM_COPY:
  302.         case DTM_WRITE:
  303.             retval = Sound_WRITE( cl, o, (struct dtWrite *)msg );
  304.         break;
  305.  
  306.         case DTM_SELECT:
  307.             retval = Sound_SELECT( cl, o, (struct dtSelect *) msg );
  308.         break;
  309.  
  310.         case DTM_CLEARSELECTED:
  311.             retval = Sound_CLEARSELECTED( cl, o, (struct dtGeneral *) msg );
  312.         break;
  313.         
  314.         case DTM_OBTAINDRAWINFO:
  315.         {
  316.             struct InstanceData    *id = INST_DATA( cl, o );
  317.             
  318.             dbug( kprintf( "DTM_OBTAINDRAWINFO\n" ); )
  319.             
  320.             retval =    (    ( id->Screen = (struct Screen *) GetTagData( PDTA_Screen, NULL, ((struct opSet *)msg)->ops_AttrList ) ) ||
  321.                         ( id->DrawInfo = (struct DrawInfo *) GetTagData( GA_DrawInfo, NULL, ((struct opSet *)msg)->ops_AttrList ) ) );
  322.         }
  323.         break;
  324.         
  325.         case DTM_DRAW:
  326.             retval = Sound_DRAW( cl, o, (struct dtDraw *) msg );
  327.         break;
  328.         
  329.         case DTM_RELEASEDRAWINFO:
  330.         
  331.             dbug( kprintf( "DTM_RELEASEDRAWINFO\n" ); )
  332.             
  333.             retval = 0L;
  334.         break;
  335.         
  336.         case DTM_REMOVEDTOBJECT:
  337.         {
  338.             struct InstanceData    *id = INST_DATA( cl, o );
  339.             /* prevent other tasks (cursor- or playertask) from reading this */
  340.             dbug( kprintf( "DTM_REMOVEDTOBJECT\n" ); )
  341.             
  342.             ObtainSemaphore( &id->Lock );
  343.             id->Window = (struct Window *)
  344.             id->Requester = NULL;
  345.             ReleaseSemaphore( &id->Lock );
  346.             
  347.             if( id->ColorMap )
  348.             {
  349.                 ReleasePen( id->ColorMap, id->BackgroundPen );
  350.                 ReleasePen( id->ColorMap, id->WaveformPen );
  351.             }
  352.         }
  353.         
  354.         default:
  355.             dbug( kprintf("METHOD: %08lx\n", msg->MethodID); )
  356.             retval = (ULONG) DoSuperMethodA(cl, o, msg);
  357.     }
  358.  
  359.     return(retval);
  360. }
  361.  
  362. /****************************************************************************/
  363.  
  364. #ifdef __MAXON__
  365. ULONG NotifyAttrs( Object *o, struct GadgetInfo *ginfo, ULONG flags, Tag tag1, ... )
  366. {
  367.     struct opUpdate opu;
  368.  
  369.     opu . MethodID     = OM_NOTIFY;
  370.     opu . opu_AttrList = (struct TagItem *)(&tag1);
  371.     opu . opu_GInfo    = ginfo;
  372.     opu . opu_Flags    = flags;
  373.  
  374.     return( DoMethodA( o, (Msg)(&opu) ) );
  375. }
  376. #endif
  377.  
  378. /****************************************************************************/
  379.  
  380. LONG SendObjectMsg( struct InstanceData *id, ULONG Command, APTR Data )
  381. {
  382. #ifndef __MAXON__
  383. #undef SysBase
  384.     struct Library        *SysBase = (*(struct Library **)4L);
  385. #endif
  386.     struct ObjectMsg    *msg;
  387.  
  388.     if( msg = AllocVec( sizeof( *msg ), MEMF_PUBLIC|MEMF_CLEAR ) )
  389.     {
  390.         msg->Command = Command;
  391.         msg->Data = Data;
  392.         PutMsg( id->PlayerPort, &msg->Message );
  393.     }
  394.     else
  395.     {
  396.         dbug( kprintf( "No memory to send objmsg\n" ); )
  397.     }
  398.     
  399.     return( (LONG) (msg!=NULL) );/*
  400.  
  401.     struct MsgPort    *replyport;
  402.     LONG            err = ERROR_NO_FREE_STORE;
  403. #ifdef NO_SIGB_SINGLE_PORT
  404.     replyport = CreateMsgPort();
  405.     if( msg = (struct ObjectMsg *) CreateIORequest( replyport, sizeof( *msg ) ) )
  406.     {
  407.         msg->Command = Command;
  408.         msg->Data = Data;
  409.         PutMsg( id->PlayerPort, &msg->Message );
  410.         WaitPort( replyport );
  411.         GetMsg( replyport );
  412.         //err = msg->ErrorCode;
  413.         DeleteIORequest( (struct IORequest *) msg );
  414.     }
  415.     DeleteMsgPort( replyport );
  416.     return TRUE;
  417. #else
  418.     if( replyport = AllocVec( sizeof( *replyport ) + sizeof( *msg ), MEMF_PUBLIC|MEMF_CLEAR ) )
  419.     {
  420.         replyport->mp_SigTask = FindTask( NULL );
  421.         replyport->mp_SigBit = SIGB_SINGLE;
  422.         NewList( &replyport->mp_MsgList );
  423.                 
  424.         msg = (struct ObjectMsg *) (replyport+1);
  425.         msg->Message.mn_ReplyPort = replyport;
  426.                 
  427.         msg->Command = Command;
  428.         msg->Data = Data;
  429.         SetSignal( 0L, SIGF_SINGLE );
  430.         PutMsg( id->PlayerPort, &msg->Message );
  431.         WaitPort( replyport );
  432.         GetMsg( replyport );
  433.         err = msg->ErrorCode;
  434.         FreeVec( replyport );
  435.         return TRUE;
  436.     }
  437. #endif
  438.     return NULL;
  439. */
  440. #ifndef __MAXON__
  441. #define SysBase    cb->cb_SysBase
  442. #endif
  443. }
  444.  
  445. /****************************************************************************/
  446.  
  447. LONG __regargs Sound_CLEARSELECTED( Class *cl, Object *o, struct dtGeneral *dtg )
  448. {
  449.     struct RastPort        *rp;
  450.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  451.     struct ClassBase        *cb = (struct ClassBase *) cl->cl_UserData;
  452.     LONG                retval = 0L;
  453.     
  454.     dbug( kprintf( "DTM_CLEARSELECTED\n"); )
  455.     
  456.     /* 'magic' nothing selected value */
  457.     id->MinX =
  458.     id->MaxX = ~0; 
  459.     id->StartSample =
  460.     id->EndSample = ~0L;
  461.     
  462.     if( rp = ObtainGIRPort( dtg->dtg_GInfo ) )
  463.     {
  464.         DoMethod( o, GM_RENDER, (ULONG) dtg->dtg_GInfo, (ULONG) rp, (ULONG) GREDRAW_REDRAW );
  465.         ReleaseGIRPort( rp );
  466.     }
  467.     
  468.     ((struct DTSpecialInfo *)(G( o ) -> SpecialInfo)) -> si_Flags &= ~DTSIF_HIGHLIGHT;
  469.     
  470.     return retval;
  471. }
  472.  
  473. /****************************************************************************/
  474.  
  475. LONG __regargs Sound_SELECT( Class *cl, Object *o, struct dtSelect *dts )
  476. {
  477.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  478.     struct ClassBase        *cb = (struct ClassBase *) cl->cl_UserData;
  479.     WORD                minX = id->MinX, maxX = id->MaxX, oldx, 
  480.                         x = G(o)->LeftEdge, w = G(o)->Width;
  481.     ULONG                samplelength = id->SampleLength,
  482.                         startSample = ~0L, endSample = ~0L;
  483.     LONG                dy = samplelength, dx, error, add, sub, step = 1L, i,
  484.                         retval = 0L;
  485.  
  486.     dbug( kprintf("DTM_SELECT\n"); )
  487.  
  488.     if( minX > maxX )
  489.     {
  490.         maxX = minX;
  491.         minX = id->MaxX;
  492.     }
  493.     /* get abs xpos/width */
  494.     if( G(o)->Flags & GFLG_RELWIDTH )
  495.     {
  496.         w += dts->dts_GInfo->gi_Domain.Width;
  497.     }
  498.     
  499.     if( G(o)->Flags & GFLG_RELRIGHT )
  500.     {
  501.         x += dts->dts_GInfo->gi_Domain.Left;
  502.     }
  503.     
  504.     oldx = x+=4; w-=8;
  505.     
  506.     dx = w;
  507.     /* a big sample */
  508.     if( samplelength >> 17 )
  509.     {
  510.         dy >>= 7;
  511.         step = 128;
  512.     }
  513.     /* get first and last sample of the marked area by
  514.     ** comparing the coordinates */
  515.     if( samplelength <= w )
  516.     {
  517.         LONG    c = 0L;
  518.  
  519.         error = dy-2*dx-1;    
  520.         sub = 2*(dx+1); add = 2*(dy+1); 
  521.     
  522.         for( i = w; i; i-- ) 
  523.         {
  524.             if( x >= minX && startSample == ~0L )
  525.             {
  526.                 startSample = c;
  527.             } 
  528.             else if( x++ >= maxX )
  529.             {
  530.                 endSample = c;
  531.                 break;
  532.             }
  533.             
  534.             if( error > 0 ) 
  535.             {
  536.                 c += step;
  537.                 error -= sub;
  538.             }
  539.         
  540.             error += add;
  541.         }
  542.     }
  543.     else
  544.     {        
  545.         error = dx-2*dy-1;       
  546.         sub = 2*(dy+1); add = 2*(dx+1);
  547.     
  548.         for( i = 0; i < samplelength; i+=step )
  549.         {
  550.             if( error > 0 )
  551.             {
  552.                 if( x >= minX && startSample == ~0L )
  553.                 {
  554.                     startSample = i;
  555.                 }
  556.                 else if( x++ >= maxX )
  557.                 {
  558.                     endSample = i;
  559.                     break;
  560.                 }
  561.                 
  562.                 error -= sub;
  563.             } 
  564.         
  565.             error += add;
  566.         }
  567.     }
  568.     /* some corrections */
  569.     if( endSample == ~0L )
  570.     {
  571.         endSample = samplelength;
  572.     }
  573.     
  574.     if( minX == oldx)
  575.     {
  576.         startSample = 0L;
  577.     }
  578.     
  579.     id->StartSample = startSample;
  580.     id->EndSample = endSample;
  581.     
  582.     dbug( kprintf( "%ld, %ld\n", startSample, endSample ); )
  583.  
  584.     return retval;
  585. }
  586.  
  587. /****************************************************************************/
  588.  
  589. void __regargs GetSoundDTPrefs( struct ClassBase *cb )
  590. {
  591.     TEXT            buf[256];
  592.     LONG            len;
  593.  
  594.     dbug( kprintf( "GetSoundDTPrefs\n" ); )
  595.  
  596.     ObtainSemaphore( &cb->cb_LibLock );
  597.     
  598.     /* set default settings */
  599.     dbug( kprintf( "Setting default values\n" ); )
  600.     cb->cb_AHI = FALSE;
  601.     cb->cb_AHIModeID = AHI_DEFAULT_ID;
  602.     cb->cb_ForceAHIMode = FALSE;
  603.     cb->cb_AHIMixFrequency = AHI_DEFAULT_FREQ;
  604.     
  605.     cb->cb_Compress    = FALSE;
  606.     cb->cb_AIFF        = FALSE;
  607.  
  608.     cb->cb_NomWidth    = 160;
  609.     cb->cb_NomHeight    = 100;
  610.     
  611.     cb->cb_BgCol[0] =
  612.     cb->cb_BgCol[1] =
  613.     cb->cb_BgCol[2] = 0;
  614.     
  615.     cb->cb_WfCol[0] = 35 << 24L;
  616.     cb->cb_WfCol[1] = 204 << 24L;
  617.     cb->cb_WfCol[2] = 23 << 24L;
  618.     
  619.     cb->cb_BufferSize = 65536L;
  620.     cb->cb_Volume = 64L;
  621.     cb->cb_ControlPanel = FALSE;
  622.     cb->cb_NoGTSlider = FALSE;
  623.     
  624.     if( ( len = GetVar( "datatypes/sounddt41.prefs", buf, sizeof( buf )-1, GVF_GLOBAL_ONLY ) ) > 0 )
  625.     {
  626.         struct RDArgs    *rdargs;
  627.         
  628.         dbug( kprintf( "Prefs: %s\n", buf ); )
  629.  
  630.         if( rdargs = AllocDosObject( DOS_RDARGS, NULL ) )
  631.         {
  632.             struct RDArgs    *freeargs;
  633.             struct {
  634.                 LONG    *volume;
  635.                 LONG    *buffersize;
  636.                 LONG    ahi;
  637.                 STRPTR    ahimodeid;
  638.                 LONG    forceahimode;
  639.                 LONG    *mixfreq;
  640.                 LONG    aiff;
  641.                 LONG    compress;
  642.                 LONG    *width, *height;
  643.                 STRPTR    bg, wf;
  644.                 LONG    cp;
  645.                 LONG    nogtsl;            
  646.             } args = { };
  647.         
  648.             /* prepare rdargs */
  649.             buf[len++] = '\n';
  650.             rdargs->RDA_Source.CS_Buffer = buf;
  651.             rdargs->RDA_Source.CS_Length = len;
  652.             rdargs->RDA_Flags = RDAF_NOPROMPT;
  653.         
  654.             if( freeargs = ReadArgs( TEMPLATE, (LONG *)&args, rdargs ) )
  655.             {
  656.                 dbug( kprintf( "List of options:\n" ); )
  657.                 
  658.                 if( args.ahi )
  659.                 {
  660.                     cb->cb_AHI = TRUE;
  661.                     dbug( kprintf( "AHI\n" ); )
  662.                 }
  663.                 
  664.                 if( args.ahimodeid )
  665.                 {
  666.                     cb->cb_AHIModeID = Hex2Long( args.ahimodeid );
  667.                     dbug( kprintf( "AHIMODEID = %lx\n", cb->cb_AHIModeID ); )
  668.                 }
  669.                 
  670.                 if( args.forceahimode )
  671.                 {
  672.                     cb->cb_ForceAHIMode = TRUE;
  673.                     dbug( kprintf( "FAM\n" ); )
  674.                 }
  675.                 
  676.                 if( args.mixfreq )
  677.                 {
  678.                     cb->cb_AHIMixFrequency = *args.mixfreq;
  679.                     dbug( kprintf( "AHIMIXFREQ = %ld\n", *args.mixfreq ); )
  680.                 }
  681.                 
  682.                 if( args.aiff )
  683.                 {
  684.                     cb->cb_AIFF = TRUE;
  685.                     dbug( kprintf( "AIFF16\n" ); )
  686.                 }
  687.                 
  688.                 if( args.compress )
  689.                 {
  690.                     cb->cb_Compress = TRUE;
  691.                     dbug( kprintf( "COMPRESS\n" ); )
  692.                 }
  693.                 
  694.                 if( args.width )
  695.                 {
  696.                     cb->cb_NomWidth = *args.width;
  697.                     dbug( kprintf( "WIDTH = %ld\n", *args.width ); )
  698.                 }
  699.                 
  700.                 if( args.height )
  701.                 {
  702.                     cb->cb_NomHeight = *args.height;
  703.                     dbug( kprintf( "HEIGHT = %ld\n", *args.height ); )
  704.                 }
  705.                 
  706.                 if( args.wf )
  707.                 {
  708.                     LONG    num = Hex2Long( args.wf );
  709.                     
  710.                     cb->cb_WfCol[0] = (num>>16L)<<24;
  711.                     cb->cb_WfCol[1] = (num>>8L)<<24L;
  712.                     cb->cb_WfCol[2] = (num)<<24L;
  713.                     dbug( kprintf( "WFCOL = %08lx\n", num ); )
  714.                 }
  715.                 
  716.                 if( args.bg )
  717.                 {
  718.                     LONG    num = Hex2Long( args.bg );
  719.                     
  720.                     cb->cb_BgCol[0] = (num>>16L)<<24L;
  721.                     cb->cb_BgCol[1] = (num>>8L)<<24L;
  722.                     cb->cb_BgCol[2] = (num)<<24L;
  723.                     dbug( kprintf( "BGCOL = %08lx\n", num ); )
  724.                 }
  725.                 
  726.                 if( args.buffersize )
  727.                 {
  728.                     LONG    bufsize = *args.buffersize;
  729.                     
  730.                     if( bufsize > 1023 && bufsize < 131073 )
  731.                     {
  732.                         cb->cb_BufferSize = bufsize;
  733.                     }
  734.                     
  735.                     dbug( kprintf( "BUFFERSZ = %ld\n", bufsize ); )
  736.                 }
  737.                 
  738.                 if( args.cp )
  739.                 {
  740.                     cb->cb_ControlPanel = TRUE;
  741.                     dbug( kprintf( "CP=YES\n" ); )
  742.                 }
  743.                 else
  744.                 {
  745.                     cb->cb_ControlPanel = FALSE;
  746.                     dbug( kprintf( "CP=NO\n" ); )
  747.                 }
  748.                 
  749.                 if( args.volume )
  750.                 {
  751.                     cb->cb_Volume = *args.volume;
  752.                     dbug( kprintf( "VOLUME = %ld\n", *args.volume ); )
  753.                 }
  754.                 
  755.                 if( args.nogtsl )
  756.                 {
  757.                     cb->cb_NoGTSlider = TRUE;
  758.                     dbug( kprintf( "NOGTSLIDER\n" ); )
  759.                 }
  760.                 
  761.                 FreeArgs( freeargs );
  762.             }
  763.             else
  764.             {
  765.                 extern TEXT        LibName[];
  766.                 struct EasyStruct    es = { sizeof(struct EasyStruct), NULL, LibName, buf, "Okay" };
  767.                 
  768.                 if( Fault( IoErr(), "Error in prefs file", buf, sizeof( buf ) ) )
  769.                 {
  770.                     dbug( kprintf( "Prefserr: %s\n" , buf ); )
  771.                     EasyRequestArgs( NULL, &es, NULL, NULL );
  772.                 }
  773.             }
  774.                             
  775.             FreeDosObject( DOS_RDARGS, rdargs );
  776.         }
  777.         else
  778.         {
  779.             dbug( kprintf( "AllocDosObject() failed\n" ); )
  780.         }
  781.     }
  782.     else
  783.     {
  784.         dbug( kprintf( "GetVar failed\n" ); )
  785.     }
  786.     
  787.     ReleaseSemaphore( &cb->cb_LibLock );
  788. }
  789.  
  790. /****************************************************************************/
  791.  
  792. LONG hex2long(STRPTR s)
  793. { ULONG a;
  794.   BYTE c;
  795.  
  796.   if (s && (c=*s++) && (c=='$' || (c == '0' && *s++ == 'x'))) {
  797.     a=0;
  798.     while ((c=*s++)) {
  799.       if (c>'9')
  800.         c&=0x5f;
  801.       if ((c-='0')<0 || (c>9 && (c-=7)>15))
  802.         return 0;
  803.       a<<=4,a|=c;
  804.     }
  805.     return a;
  806.   }
  807.   return 0;
  808. }
  809.  
  810. /****************************************************************************/
  811.  
  812. void CreateTapeDeck( struct ClassBase *cb, struct InstanceData *id, Object *o )
  813. {
  814. #ifdef __MAXON__
  815.     extern struct Library    *TapeDeckBase;
  816. #else
  817. #define TapeDeckBase        cb->cb_TapeDeckBase
  818. #endif
  819.     ULONG                cp;
  820.         
  821.     dbug( kprintf( "Creating panel\n" ); )
  822.     
  823.     GetDTAttrs( o, DTA_ControlPanel, (ULONG) &cp, TAG_DONE );
  824.  
  825.     if( TapeDeckBase && cp )
  826.     {
  827.         STATIC struct TagItem    prop2vol[] = { PGA_Top, SDTA_Volume, TAG_END };
  828.         
  829.         ObtainSemaphoreShared( &cb->cb_LibLock );
  830.         
  831.         if( id->VolumeSlider = NewObject( NULL, PROPGCLASS,
  832.             PGA_Top, id->Volume,
  833.             PGA_Visible, 1L,
  834.             PGA_Total, 64L,
  835.             PGA_Freedom, FREEHORIZ,
  836.             PGA_NewLook, cb->cb_NoGTSlider,
  837.             ! cb->cb_NoGTSlider ? PGA_Borderless : TAG_IGNORE, TRUE,
  838.             ICA_TARGET, (ULONG) o,
  839.             ICA_MAP, (ULONG) prop2vol,
  840.             TAG_DONE ) )
  841.         {
  842.             if( id->TapeDeckGadget = NewObject( NULL, "tapedeck.gadget",
  843.                 TDECK_Tape, TRUE,
  844.                 TAG_DONE ) )
  845.             {
  846.                 ReleaseSemaphore( &cb->cb_LibLock );
  847.                 return;
  848.             }
  849.             
  850.             DisposeObject( id->VolumeSlider );
  851.             id->VolumeSlider = NULL;
  852.         }
  853.         
  854.         ReleaseSemaphore( &cb->cb_LibLock );
  855.     }
  856.     else
  857.     {
  858.         dbug( kprintf( "Failed or turned off\n" ); )
  859.     }
  860.     
  861.     id->ControlPanel = FALSE;
  862. }
  863.  
  864. /****************************************************************************/
  865.  
  866. ULONG __regargs Sound_NEW( Class *cl, Object *o, struct opSet *ops )
  867. {
  868.     struct ClassBase    *cb = (struct ClassBase *)cl->cl_UserData;
  869.     struct TagItem    ti[6];
  870.  
  871.     dbug( kprintf( "OM_NEW\n" ); )
  872.     
  873.     GetSoundDTPrefs( cb );
  874.  
  875.     ObtainSemaphoreShared( &cb->cb_LibLock );
  876.     ti[0].ti_Tag = DTA_NominalHoriz;
  877.     ti[0].ti_Data = cb->cb_NomWidth;
  878.     ti[1].ti_Tag = DTA_NominalVert;
  879.     ti[1].ti_Data = cb->cb_NomHeight;
  880.     ti[2].ti_Tag = DTA_VertUnit;
  881.     ti[2].ti_Data = 1L;
  882.     ti[3].ti_Tag = DTA_HorizUnit;
  883.     ti[3].ti_Data = 1L;
  884.     ti[4].ti_Tag = DTA_ControlPanel;
  885.     ti[4].ti_Data = cb->cb_ControlPanel;
  886.     ti[5].ti_Tag = TAG_MORE;
  887.     ti[5].ti_Data = (ULONG) ops->ops_AttrList;
  888.     ReleaseSemaphore( &cb->cb_LibLock );
  889.         
  890.     ops->ops_AttrList = ti;
  891.     
  892.     if( o = (Object *) DoSuperMethodA( cl, o, (Msg) ops ) )
  893.     {
  894.         struct InstanceData    *id = INST_DATA( cl, o );
  895.         struct ObjectMsg        *msg;
  896.         struct MsgPort        *replyport;
  897.  
  898.         id->Volume = cb->cb_Volume;
  899.         id->Frequency = Period2Freq( 394 );
  900.         id->Cycles = 1;
  901.         id->SignalBit = -1;
  902. //        id->SampleType = SDTST_M8S;
  903.         id->Panning = 0x8000;
  904.         /* 'magic' nothing selected value */
  905.         id->MinX = 
  906.         id->MaxX = ~0L;
  907.         id->StartSample =
  908.         id->EndSample = ~0L;
  909.         id->TapeDeckHeight = 15L; // tapedeck.gadget is currently limited to 15 pixels
  910.         id->BackgroundPen =
  911.         id->WaveformPen = -1;
  912.         id->ClassBase = cb;
  913.         InitSemaphore( &id->Lock );
  914.         
  915.         /* create process */
  916.         replyport = CreateMsgPort();
  917.     
  918.         if( msg = (struct ObjectMsg *) CreateIORequest( replyport, sizeof( *msg ) ) )
  919.         {
  920.             extern UBYTE        LibName[];
  921.  
  922.             ObtainSemaphoreShared( &cb->cb_LibLock );
  923.  
  924.             if( id->PlayerProc = CreateNewProcTags(
  925.                 NP_Name, (ULONG) LibName,
  926.                 NP_Entry, (ULONG) (cb->cb_AHI) ? (ULONG) PlayerProcAHI : (ULONG) PlayerProc,
  927.                 NP_Priority, 19L,
  928.                 TAG_DONE ) )
  929.             {
  930.                 msg->Data = (APTR) id;
  931.                 msg->Command = COMMAND_INIT;
  932.                 PutMsg( &id->PlayerProc->pr_MsgPort, &msg->Message );
  933.                 WaitPort( replyport );
  934.                 GetMsg( replyport );
  935.             
  936.                 if( msg->Data )
  937.                 {
  938.                     id->PlayerPort = (struct MsgPort *) msg->Data;
  939.                 }
  940.                 else
  941.                 {
  942.                     id->PlayerProc = NULL;
  943.                 }
  944.             }
  945.         
  946.             ReleaseSemaphore( &cb->cb_LibLock );
  947.         
  948.             DeleteIORequest( (struct IORequest *) msg );
  949.             
  950.             if( id->PlayerProc )
  951.             {                
  952.                 parsetaglist( cl, o, ops );        
  953.                 CreateTapeDeck( cb, id, o );
  954.             }
  955.             else
  956.             {
  957.                 CoerceMethod( cl, o, OM_DISPOSE );
  958.                 o = NULL;
  959.             }
  960.         }
  961.         else
  962.         {
  963.             dbug( kprintf( "No memory for ioreq or msgport\n" ); )
  964.         }
  965.     
  966.         DeleteMsgPort( replyport );
  967.     }
  968.     else
  969.     {
  970.         dbug( kprintf( "OM_NEW failed\n" ); )
  971.     }
  972.     
  973.     ops->ops_AttrList = (struct TagItem *) ti[5].ti_Data;
  974.     
  975.     dbug( if( !o ) kprintf("Object creation failed\n"); )
  976.     
  977.     return( (ULONG) o );
  978. }
  979.  
  980. /****************************************************************************/
  981.  
  982. void __regargs SetVSlider( struct ClassBase *cb, struct InstanceData *id )
  983. {
  984.     /* this function works aroung a "spilled register" error */
  985.     if( id->ControlPanel )
  986.     {
  987.         ULONG    top;
  988.         GetAttr( PGA_Top, id->VolumeSlider, &top );
  989.         if( top != id->Volume ) // avoid loops
  990.         {
  991.             SetGadgetAttrs( id->VolumeSlider, id->Window, id->Requester,
  992.                 PGA_Top, id->Volume, TAG_DONE );
  993.         }
  994.     }
  995. }
  996.  
  997. /****************************************************************************/
  998.  
  999. BOOL __regargs parsetaglist( Class *cl, Object *o, struct opSet *ops )
  1000. {
  1001.     struct ClassBase    *cb = (struct ClassBase *) cl->cl_UserData;
  1002.     struct TagItem    *ti, *tstate = ops->ops_AttrList;
  1003.     struct InstanceData *id = INST_DATA( cl, o );
  1004.     BOOL            change = FALSE, newSample = FALSE;
  1005.  
  1006.     ObtainSemaphore( &id->Lock );
  1007.  
  1008.     while( ti = NextTagItem( &tstate ) )
  1009.     {
  1010.         ULONG    data = ti->ti_Data;
  1011.         
  1012.         switch( ti->ti_Tag )
  1013.         {
  1014.             case SDTA_VoiceHeader:
  1015.                 id->VoiceHeader = *(struct VoiceHeader *) data;
  1016.                 dbug( kprintf("SDTA_VoiceHeader\n"); )
  1017.             break;
  1018.             
  1019.             case SDTA_Sample:
  1020.                 id->Sample = (BYTE *) data;
  1021.                 dbug( kprintf("SDTA_Sample = %08lx\n", data); )
  1022.                 newSample = TRUE;
  1023.             break;
  1024.             
  1025.             case SDTA_SampleLength:
  1026.                 id->SampleLength = data;
  1027.                 dbug( kprintf("SDTA_SampleLength = %ld\n", data); )
  1028.             break;
  1029.             
  1030.             case SDTA_Period:
  1031.                 id->Frequency = (UWORD) Period2Freq( data );
  1032.                 change = TRUE;
  1033.                 dbug( kprintf("SDTA_Period = %ld (%ldHz)\n", data, Period2Freq(data) ); )
  1034.             break;
  1035.             
  1036.             case SDTA_Volume:
  1037.                 id->Volume = (UWORD) data;
  1038.                 change = TRUE;
  1039.                 
  1040.                 SetVSlider( cb, id );
  1041.                 
  1042.                 dbug( kprintf("SDTA_Volume = %ld\n", data); )
  1043.             break;
  1044.             
  1045.             case SDTA_Cycles:
  1046.                 id->Cycles = (UWORD) data;
  1047.                 dbug( kprintf("SDTA_Cycles = %ld\n", data); )
  1048.             break;
  1049.             
  1050.             case SDTA_SignalTask:
  1051.                 id->SignalTask = (struct Task *) data;
  1052.                 dbug( kprintf("SDTA_SignalTask = %08lx\n", data); )
  1053.             break;
  1054.             
  1055.             case SDTA_SignalBit:
  1056.                 id->SignalBit = (BYTE) data;
  1057.                 dbug( kprintf("SDTA_SignalBit = %ld\n", data); )
  1058.             break;
  1059.             
  1060.             case SDTA_Continuous:
  1061.                 id->Continuous = (BOOL) data;
  1062.                 dbug( kprintf("SDTA_Continuous = %ld\n", data); )
  1063.             break;
  1064.  
  1065.             case SDTA_SampleType:
  1066.                 id->SampleType = data;
  1067.                 dbug( kprintf("SDTA_SampleType = %ld\n", data ); )
  1068.             break;
  1069.             
  1070.             case SDTA_Panning:
  1071.                 id->Panning = data;
  1072.                 change = TRUE;
  1073.                 dbug( kprintf("SDTA_Panning = %05lx\n", data ); )
  1074.             break;
  1075.             
  1076.             case SDTA_Frequency:
  1077.                 id->Frequency = data;
  1078.                 change = TRUE;
  1079.                 dbug( kprintf("SDTA_Frequency =%ld\n", data); )
  1080.             break;
  1081.             
  1082.             case DTA_ControlPanel:
  1083.                 if( data != id->ControlPanel )
  1084.                 {
  1085.                     id->ForceRefresh = TRUE;
  1086.                 }
  1087.             
  1088.                 id->ControlPanel = (BOOL) data;
  1089.                 dbug( kprintf("DTA_ControlPanel =%ld\n", data); )
  1090.             break;
  1091.             
  1092.             case DTA_Immediate:
  1093.                 if( ! ( id->Immediate = data ) )
  1094.                 {
  1095.                     CoerceMethod( cl, o, DTM_TRIGGER, NULL, STM_STOP, NULL );
  1096.                 }
  1097.                 else
  1098.                 {
  1099.                     newSample = ( id->Sample != NULL );
  1100.                     id->DelayedImmed = TRUE;                    
  1101.                 }
  1102.             break;
  1103.             
  1104.             case DTA_Repeat:
  1105.                 id->Repeat = (BOOL) data;
  1106.             break;
  1107.             
  1108.             default:
  1109.                 dbug( kprintf("Attr: %08lx\n", ti->ti_Tag); )
  1110.         }
  1111.     }
  1112.     
  1113.     ReleaseSemaphore( &id->Lock );
  1114.     
  1115.     /*- inform sound object handler about that change -*/
  1116.     if( change && id->PlayerProc )
  1117.     {
  1118.         SendObjectMsg( id, COMMAND_PERVOL, NULL );
  1119.     }
  1120.     
  1121.     if( newSample )
  1122.     {
  1123.         /* continuous stream of data ? */
  1124.         if( id->Continuous )
  1125.         {
  1126.             /* inform player process that we got a new buffer */
  1127.             SendObjectMsg( id, COMMAND_NEXT_BUFFER, NULL );
  1128.         }
  1129.         else if( id->Immediate && id->DelayedImmed )
  1130.         {
  1131.             id->DelayedImmed = FALSE;
  1132.             CoerceMethod( cl, o, DTM_TRIGGER, NULL, STM_PLAY, NULL );
  1133.         }
  1134.     }
  1135.     
  1136.     return( change );
  1137. }
  1138.  
  1139. /****************************************************************************/
  1140.  
  1141. ULONG __regargs Sound_GET( Class *cl, Object *o, struct opGet *opg )
  1142. {
  1143.     struct ClassBase        *cb = (struct ClassBase *) cl->cl_UserData;
  1144.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  1145.     ULONG                retval = TRUE, data;
  1146.     
  1147.     dbug( kprintf("OM_GET\n"); )
  1148.     
  1149.     switch( opg->opg_AttrID )
  1150.     {
  1151.         case SDTA_VoiceHeader:
  1152.             data = (ULONG) &id->VoiceHeader;
  1153.             dbug( kprintf("SDTA_VoiceHeader\n"); )
  1154.         break;
  1155.         
  1156.         case SDTA_Sample:
  1157.             data = (ULONG) id->Sample;
  1158.             dbug( kprintf("SDTA_Sample\n"); )
  1159.         break;
  1160.         
  1161.         case SDTA_SampleLength:
  1162.             data = id->SampleLength;
  1163.             dbug( kprintf("SDTA_SampleLength\n"); )
  1164.         break;
  1165.         
  1166.         case SDTA_Period:
  1167.             data = (ULONG) Freq2Period( id->Frequency );
  1168.             dbug( kprintf("SDTA_Period\n"); )
  1169.         break;
  1170.         
  1171.         case SDTA_Volume:
  1172.             data = (ULONG) id->Volume;
  1173.             dbug( kprintf("SDTA_Volume\n"); )
  1174.         break;
  1175.         
  1176.         case SDTA_Cycles:
  1177.             data = (ULONG) id->Cycles;
  1178.             dbug( kprintf("SDTA_Cycles\n"); )
  1179.         break;
  1180.         
  1181.         case SDTA_SignalTask:
  1182.             data = (ULONG) id->SignalTask;
  1183.             dbug( kprintf("SDTA_SignalTask\n"); )
  1184.         break;
  1185.         
  1186.         case SDTA_SignalBit:
  1187.             data = (ULONG) id->SignalBit;
  1188.             dbug( kprintf("SDTA_SignalBit\n"); )
  1189.         break;
  1190.         
  1191.         case SDTA_Continuous:
  1192.             data = (ULONG) id->Continuous;
  1193.             dbug( kprintf("SDTA_Continuous\n"); )
  1194.         break;
  1195.  
  1196.         case SDTA_Panning:
  1197.             data = id->Panning;
  1198.             dbug( kprintf("SDTA_Panning\n"); )
  1199.         break;
  1200.         
  1201.         case SDTA_SampleType:
  1202.             data = id->SampleType;
  1203.             dbug( kprintf("SDTA_SampleType\n"); )
  1204.         break;
  1205.         
  1206.         case SDTA_Frequency:
  1207.             data = id->Frequency;
  1208.             dbug( kprintf("SDTA_Frequency\n"); )
  1209.         break;
  1210.         
  1211.         case DTA_TriggerMethods:
  1212.             data = (ULONG) TriggerMethods;
  1213.             dbug( kprintf("SDTA_TriggerMethods\n"); )
  1214.         break;
  1215.         
  1216.         case DTA_ControlPanel:
  1217.             data = (ULONG) id->ControlPanel;
  1218.             dbug( kprintf("DTA_ControlPanel\n"); )
  1219.         break;
  1220.         
  1221.         case DTA_Repeat:
  1222.             data = (ULONG) id->Repeat;
  1223.         break;
  1224.  
  1225.         case DTA_Immediate:
  1226.             data = (ULONG) id->Immediate;
  1227.         break;
  1228.  
  1229.         case DTA_Methods:
  1230.         {
  1231.             dbug( kprintf( "DTA_Methods\n"); )
  1232. #ifndef __GNUC__ 
  1233.             ObtainSemaphore( &cb->cb_LibLock );
  1234.             /* first request of DTA_Methods ? */
  1235.             if( ! ( data = (ULONG) cb->cb_Methods ) )
  1236.             {
  1237.                 ULONG    cntSuper, cntMethods, *superMethods, *newMethods;
  1238.                 /* create Methods array */
  1239.                 DoSuperMethod( cl, o, OM_GET, DTA_Methods, (ULONG) &superMethods );
  1240.                 
  1241.                 for( cntSuper = 0; superMethods[ cntSuper ] != ~0L; cntSuper++ ) {}
  1242.                 for( cntMethods = 0; Methods[ cntMethods ] != ~0L; cntMethods++ ) {}
  1243.                 
  1244.                 cb->cb_Methods = // For any reasons, GNUC seems to have problems here !
  1245.                 newMethods = (ULONG *) AllocVec( ( cntSuper+cntMethods+1UL ) * sizeof( ULONG ), MEMF_PUBLIC );
  1246.                 
  1247.                 if( data = (ULONG) newMethods )
  1248.                 {
  1249.                     ULONG    num = 0L;
  1250.  
  1251.                     CopyMem( superMethods, newMethods, sizeof( ULONG ) * cntSuper );
  1252.                     newMethods += cntSuper;
  1253.                 
  1254.                     for( num = 0; num < cntMethods; num++ )
  1255.                     {
  1256.                         ULONG    i, method = Methods[ num ];
  1257.                         
  1258.                         for( i = 0; i < cntSuper; i++ )
  1259.                         {
  1260.                             if( superMethods[ i ] == method )
  1261.                             {
  1262.                                 break;
  1263.                             }
  1264.                         }
  1265.                         
  1266.                         if( i == cntSuper )
  1267.                         {
  1268.                             *newMethods++ = method;
  1269.                         }
  1270.                     }
  1271.                     
  1272.                     *newMethods = ~0L;
  1273.                 }
  1274.                 else 
  1275.                 {
  1276.                     data = (ULONG) Methods;
  1277.                 }
  1278.             }
  1279.             
  1280.             ReleaseSemaphore( &cb->cb_LibLock );
  1281. #else
  1282.             ObtainSemaphore( &cb->cb_LibLock );
  1283.             
  1284.             if( ! ( data = (ULONG) cb->cb_Methods ) )
  1285.             {
  1286.                 if( DataTypesBase->lib_Version >= 45L )
  1287.                 {
  1288.                     ULONG    *superMethods = NULL;
  1289.                     
  1290.                     DoSuperMethod( cl, o, OM_GET, DTA_Methods, (ULONG) &superMethods );
  1291.                     
  1292.                     data = (ULONG) ( cb->cb_Methods = CopyDTMethods( superMethods, Methods, NULL ) );
  1293.                     
  1294.                     dbug( kprintf( "CopyDTMethods returned %08lx\n", data ); )
  1295.                 }
  1296.             }
  1297.             
  1298.             if( ! data )
  1299.             {
  1300.                 data = (ULONG) Methods;
  1301.             }
  1302.             
  1303.             ReleaseSemaphore (&cb->cb_LibLock );
  1304. #endif
  1305.         }
  1306.         break;
  1307.  
  1308.         default:
  1309.             retval = FALSE;
  1310.              dbug( kprintf("Attr: %08lx\n",  opg->opg_AttrID); )
  1311.     }
  1312.     
  1313.     if( retval )
  1314.     {
  1315.         *opg->opg_Storage = data;
  1316.     }
  1317.     else
  1318.     {        
  1319.         retval = DoSuperMethodA( cl, o, (Msg) opg );
  1320.         dbug( kprintf("SuperAttr: %08lx, %08lx\n",  opg->opg_AttrID, *opg->opg_Storage); )
  1321.     }
  1322.     
  1323.     return( retval );
  1324. }
  1325.  
  1326. /****************************************************************************/
  1327.  
  1328. ULONG __regargs Sound_SET( Class *cl, Object *o, struct opSet *ops )
  1329. {
  1330.     struct ClassBase        *cb = (struct ClassBase *) cl->cl_UserData;
  1331.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  1332.     ULONG                retval;
  1333.         
  1334.     dbug( kprintf("OM_SET\n"); )
  1335.  
  1336.     retval = DoSuperMethodA( cl, o, (Msg) ops );
  1337.     
  1338.     parsetaglist( cl, o, ops );
  1339.     
  1340.     if( retval || ( ( id->ForceRefresh ) && ( id->Gadget ) ) )
  1341.     {
  1342.         struct RastPort    *rp;
  1343.         
  1344.         if( rp = ObtainGIRPort( ops->ops_GInfo ) )
  1345.         {
  1346.             DoMethod( o, GM_RENDER, (ULONG) ops->ops_GInfo, (ULONG) rp, GREDRAW_REDRAW );
  1347.             ReleaseGIRPort( rp );
  1348.             
  1349.             id->ForceRefresh = FALSE;
  1350.         }
  1351.     }
  1352.     
  1353.     return( retval );
  1354. }
  1355.  
  1356. /****************************************************************************/
  1357.  
  1358. ULONG __regargs Sound_UPDATE( Class *cl, Object *o, struct opUpdate *opu )
  1359. {
  1360.     struct ClassBase        *cb = (struct ClassBase *)cl->cl_UserData;
  1361.  
  1362.     dbug( kprintf("OM_UPDATE\n"); )
  1363.  
  1364.     return( DoMethod( o, ICM_CHECKLOOP ) ? FALSE : Sound_SET( cl, o, (struct opSet *) opu ) );
  1365. }
  1366.  
  1367. /****************************************************************************/
  1368.  
  1369. ULONG __regargs Sound_DISPOSE( Class *cl, Object *o, Msg msg )
  1370. {
  1371.     struct ClassBase        *cb = (struct ClassBase *) cl->cl_UserData;
  1372.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  1373.     struct SignalSemaphore    *lock = &((struct DTSpecialInfo *)G( o )->SpecialInfo)->si_Lock;
  1374.     
  1375.     dbug( kprintf("OM_DISPOSE\n"); )
  1376.     
  1377.     /* free playerproc stuff */
  1378.     if( id->PlayerProc )
  1379.     {
  1380.         struct MsgPort    *replyport;
  1381.         struct ObjectMsg    *msg;
  1382.         
  1383.         while( ! ( replyport = CreateMsgPort() ) )
  1384.         {
  1385.             Delay( 25L );
  1386.         }
  1387.         
  1388.         while( ! ( msg = (struct ObjectMsg *) CreateIORequest( replyport, sizeof( *msg ) ) ) )
  1389.         {
  1390.             Delay( 25L );
  1391.         }
  1392.         
  1393.         msg->Command = COMMAND_EXIT;
  1394.         PutMsg( id->PlayerPort, &msg->Message );
  1395.         WaitPort( replyport );
  1396.         GetMsg( replyport );
  1397.         
  1398.         DeleteIORequest( (struct IORequest *) msg );
  1399.         DeleteMsgPort( replyport );
  1400.     }
  1401.     /* free controls */
  1402.     dbug( kprintf( "freeing controls\n" ); )
  1403.     DisposeObject( id->TapeDeckGadget );
  1404.     DisposeObject( id->VolumeSlider );
  1405.     
  1406.     /* free sample memory, obtain semaphore in case that there's a write in progess */
  1407.     dbug( kprintf( "releasing memory\n" ); )
  1408.  
  1409.     ObtainSemaphore( lock );
  1410.     FreeVec( id->Sample );
  1411.     ReleaseSemaphore( lock );
  1412.  
  1413.     return( DoSuperMethodA( cl, o, msg ) );
  1414. }
  1415.  
  1416. /****************************************************************************/
  1417.  
  1418. ULONG __regargs Sound_DOMAIN( Class *cl, Object *o, struct gpDomain *gpd )
  1419. {
  1420.     struct ClassBase        *cb = (struct ClassBase *) cl->cl_UserData;
  1421.     struct InstanceData     *id = (struct InstanceData *) INST_DATA( cl, o );
  1422.     struct IBox            *gbox = &gpd->gpd_Domain;
  1423.  
  1424.     dbug( kprintf("GDOMAIN\n"); )
  1425.     
  1426.     *gbox = GetAbsGadgetBox( &gpd->gpd_GInfo->gi_Domain, EXTG( o ), FALSE );
  1427.  
  1428.     switch( gpd->gpd_Which )
  1429.     {
  1430.         case GDOMAIN_MINIMUM:
  1431.             gbox->Width = 32;
  1432.             gbox->Height = id->TapeDeckHeight + 10;
  1433.         break;
  1434.         
  1435.         case GDOMAIN_NOMINAL:
  1436.             ObtainSemaphoreShared( &cb->cb_LibLock );
  1437.             gbox->Width = cb->cb_NomWidth;
  1438.             gbox->Height = cb->cb_NomHeight;
  1439.             ReleaseSemaphore( &cb->cb_LibLock );
  1440.         break;
  1441.         
  1442.         case GDOMAIN_MAXIMUM:
  1443.             gbox->Width = 
  1444.             gbox->Height = SHRT_MAX;
  1445.         break;
  1446.     }
  1447.     
  1448.     return TRUE;
  1449. }
  1450.  
  1451. /****************************************************************************/
  1452.  
  1453. ULONG __regargs Sound_LAYOUT( Class *cl, Object *o, struct gpLayout *gpl )
  1454. {
  1455.     struct ClassBase        *cb = (struct ClassBase *)cl->cl_UserData;
  1456.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  1457.     struct DTSpecialInfo    *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  1458.     struct GadgetInfo        *gi = gpl->gpl_GInfo;
  1459.     struct IBox            *domain = NULL;
  1460.     STRPTR                name = NULL;
  1461.     ULONG                retval;
  1462.  
  1463.     dbug( kprintf( "GM_LAYOUT\n" ); )
  1464.  
  1465.     retval = DoSuperMethodA( cl, o, (Msg) gpl );
  1466.  
  1467.     si->si_Flags |= DTSIF_LAYOUT;
  1468.     ObtainSemaphore( &si->si_Lock );
  1469.     
  1470.     NotifyAttrs( o, gi, 0L,
  1471.         GA_ID, G( o )->GadgetID,
  1472.         DTA_Busy, TRUE,
  1473.         TAG_DONE );
  1474.  
  1475.     if( GetDTAttrs( o, 
  1476.         DTA_ObjName, (ULONG) &name,
  1477.         DTA_Domain, (ULONG) &domain,
  1478.         TAG_DONE ) == 2L )
  1479.     {    
  1480.         ULONG    vunit = si->si_VertUnit,
  1481.                 hunit = si->si_HorizUnit,
  1482.                 totalw = si->si_TotHoriz,
  1483.                 totalh = si->si_TotVert;
  1484.     
  1485.         si->si_VertUnit = vunit;
  1486.         si->si_VisVert = domain->Height / vunit;
  1487.         si->si_TotVert = totalh;
  1488.         
  1489.         si->si_HorizUnit = hunit;
  1490.         si->si_VisHoriz = domain->Width / hunit;
  1491.         si->si_TotHoriz = totalw;
  1492.  
  1493.         if( ! name )
  1494.         {
  1495.             if( ! GetDTAttrs( o, DTA_Name, (ULONG) &name, TAG_DONE ) || ! name )
  1496.             {
  1497.                 name = "Untitled";
  1498.             }
  1499.             else
  1500.             {
  1501.                 name = FilePart( name );
  1502.             }
  1503.         }
  1504.  
  1505.         if( gpl->gpl_Initial )
  1506.         {
  1507.             ObtainSemaphore( &id->Lock );
  1508.             id->Window = gi->gi_Window;
  1509.             id->Requester = gi->gi_Requester;
  1510.             id->Gadget = (struct Gadget *) o;
  1511.             ReleaseSemaphore( &id->Lock );
  1512.             /* obtain pens */
  1513.             id->ColorMap = gi->gi_Screen->ViewPort.ColorMap;
  1514.             
  1515.             ObtainSemaphoreShared( &cb->cb_LibLock );
  1516.             id->BackgroundPen = ObtainBestPenA( id->ColorMap, 
  1517.                 cb->cb_BgCol[0], cb->cb_BgCol[1], cb->cb_BgCol[2], NULL );
  1518.             id->WaveformPen = ObtainBestPenA( id->ColorMap, 
  1519.                 cb->cb_WfCol[0], cb->cb_WfCol[1], cb->cb_WfCol[2], NULL );
  1520.             ReleaseSemaphore( &cb->cb_LibLock );
  1521.         }
  1522.     
  1523.         if( id->TapeDeckGadget )
  1524.         {    
  1525.             struct gpLayout    member_gpl;                
  1526.             struct TagItem    ti[] = {
  1527.                 GA_Left, domain->Left,
  1528.                 GA_Top, domain->Top + domain->Height - id->TapeDeckHeight,
  1529.                 GA_Width, 201,
  1530.                 GA_Height, id->TapeDeckHeight,
  1531.                 TAG_DONE 
  1532.             };
  1533.             
  1534.             if( ( gpl->gpl_Initial ) && ( G( o )->GadgetType & GTYP_REQGADGET ) )
  1535.             {    
  1536.                 id->TapeDeckGadget->GadgetType |= GTYP_REQGADGET;
  1537.                 id->VolumeSlider->GadgetType |= GTYP_REQGADGET; 
  1538.             }
  1539.             
  1540.             ObtainSemaphoreShared( &cb->cb_LibLock );
  1541.         
  1542.             member_gpl = *gpl;
  1543.             member_gpl.MethodID = GM_LAYOUT;
  1544.             
  1545.             SetAttrsA( id->TapeDeckGadget, ti );
  1546.                 
  1547.             DoMethodA( (Object *) id->TapeDeckGadget, (Msg) &member_gpl );
  1548.             
  1549.             ti[0].ti_Data += 205;
  1550.             ti[2].ti_Data = domain->Width - 205;
  1551.     
  1552.             if( ! cb->cb_NoGTSlider )
  1553.             {
  1554.                 ti[0].ti_Data += 4;
  1555.                 ti[1].ti_Data += 2;
  1556.                 ti[2].ti_Data -= 8;
  1557.                 ti[3].ti_Data -= 4;
  1558.             }
  1559.             
  1560.             SetAttrsA( id->VolumeSlider, ti );
  1561.             
  1562.             DoMethodA( (Object *) id->VolumeSlider, (Msg) &member_gpl );
  1563.         
  1564.             ReleaseSemaphore( &cb->cb_LibLock );
  1565.         }
  1566.         
  1567.         NotifyAttrs( o, gi, 0L,
  1568.             GA_ID, G(o)->GadgetID,
  1569.             DTA_VisibleVert, si->si_VisVert,
  1570.             DTA_TotalVert, totalh,
  1571.             DTA_VertUnit, vunit,
  1572.             DTA_VisibleHoriz, si->si_VisHoriz,
  1573.             DTA_TotalHoriz, totalw,
  1574.             DTA_HorizUnit, hunit,
  1575.             DTA_Title, (ULONG) name,
  1576.             DTA_Busy, FALSE,
  1577.             DTA_Sync, TRUE,
  1578.             TAG_DONE );        
  1579.     }
  1580.  
  1581.     ReleaseSemaphore( &si->si_Lock );
  1582.     si->si_Flags &= ~DTSIF_LAYOUT;    
  1583.  
  1584.     return retval + si->si_TotVert;
  1585. }
  1586.  
  1587. /****************************************************************************/
  1588.  
  1589. void __regargs DrawWaveform( struct ClassBase *cb, struct RastPort *rp, struct InstanceData *id, UWORD x, UWORD y, UWORD w, UWORD h )
  1590. {
  1591.     ULONG    sampleStart = id->StartSample, sampleEnd = id->EndSample;
  1592.     LONG    samplelength = id->SampleLength, error, dx = w, dy = samplelength, sub, add, i, 
  1593.             step = 1L, k=0L, oldx=x, shift = ( id->SampleType >= SDTST_M16S ? 1 : 0 );
  1594.     BOOL    stereo = IsStereo( id->SampleType );
  1595.     WORD    minX = ~0, maxX = ~0, oldy = y, oldh = h;
  1596.     /* scaling limit is 25500% */
  1597.     if( w > (samplelength<<8) )
  1598.     {
  1599.         return;
  1600.     }
  1601.     /* a big sample, speed up rendering */
  1602.     if( samplelength >> 17 )
  1603.     {
  1604.         dy >>= 7;
  1605.         step = 128;
  1606.     }
  1607.     /* adjust ypos and height for stereo sample */
  1608.     if( stereo )
  1609.     {
  1610.         h /= 2;
  1611.         y += h/2;
  1612.         shift++;
  1613.     }
  1614.     else
  1615.     {
  1616.         y+= h/2;
  1617.     }
  1618.     
  1619.     for( k = 0; k < (stereo?2:1); k++ )
  1620.     {
  1621.         BYTE    *sample = &id->Sample[ k ];
  1622.         
  1623.         if( k && id->SampleType == SDTST_S16S )
  1624.         {
  1625.             sample++;
  1626.         }
  1627.         
  1628.         Move( rp, x, y );
  1629.         
  1630.         if( samplelength <= w )
  1631.         {
  1632.             LONG    c = 0L;
  1633.     
  1634.             error = dy-2*dx-1;    
  1635.             sub = 2*(dx+1); add = 2*(dy+1); 
  1636.             
  1637.             for( i = 0; i < w; i++ ) 
  1638.             {
  1639.                 /* get minX and maxX for highlighting */
  1640.                 if( sampleStart != ~0L )
  1641.                 {
  1642.                     if( i >= sampleStart && minX == ~0 )
  1643.                     {
  1644.                         minX = x;
  1645.                     }
  1646.                     else if( i >= sampleEnd && maxX == ~0 )
  1647.                     {
  1648.                         maxX = x;
  1649.                         sampleStart = ~0L; // speed up
  1650.                     }
  1651.                 }
  1652.                     
  1653.                 Draw( rp, x++, y + ( SMult( sample[ c << shift ], h ) >> 8 ) );
  1654.         
  1655.                 if( error > 0 ) 
  1656.                 {
  1657.                     c += step;
  1658.                     error -= sub;
  1659.                 }
  1660.                 
  1661.                 error += add;
  1662.             }
  1663.         }
  1664.         else
  1665.         {        
  1666.             error = dx-2*dy-1;       
  1667.             sub = 2*(dy+1); add = 2*(dx+1);
  1668.             
  1669.             for( i = 0; i < samplelength; i+=step )
  1670.             {
  1671.                 if( error > 0 )
  1672.                 {
  1673.                     /* get minX and maxX for highlighting */
  1674.                     if( sampleStart != ~0L )
  1675.                     {
  1676.                         if( i >= sampleStart && minX == ~0 )
  1677.                         {
  1678.                             minX = x;
  1679.                         }
  1680.                         else if( i >= sampleEnd && maxX == ~0 )
  1681.                         {
  1682.                             maxX = x;
  1683.                             sampleStart = ~0L; // speed up
  1684.                         }
  1685.                     }
  1686.                         
  1687.                     Draw( rp, x++, y + ( SMult( sample[ i << shift ], h ) >> 8 ) );
  1688.                     error -= sub;
  1689.                 } 
  1690.                 
  1691.                 error += add;
  1692.             }
  1693.         }
  1694.     
  1695.         y += h;
  1696.         x = oldx;
  1697.     }
  1698.     /* something marked ? */
  1699.     if( minX != ~0 )
  1700.     {
  1701.         if( maxX == ~0 )
  1702.         {
  1703.             maxX = oldx+w-1;
  1704.         }
  1705.  
  1706.         SetDrMd( rp, COMPLEMENT );
  1707.         RectFill( rp, minX, oldy, maxX, oldy+oldh-1 );
  1708.         /* fix tapedeck.gadget bug (?) */
  1709.         SetDrMd( rp, JAM1 );
  1710.     }
  1711. }
  1712.  
  1713. /****************************************************************************/
  1714.  
  1715. ULONG __regargs Sound_RENDER( Class *cl, Object *o, struct gpRender *gpr )
  1716. {
  1717.     struct ClassBase        *cb = (struct ClassBase *)cl->cl_UserData;
  1718.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  1719.     
  1720.     dbug( kprintf( "GM_RENDER\n" ); )
  1721.  
  1722. //    if( gpr->gpr_Redraw == GREDRAW_REDRAW )
  1723.     {
  1724.         struct RastPort        *rp = gpr->gpr_RPort;
  1725.         struct ColorMap        *cm = NULL;
  1726.         struct IBox            gbox;
  1727.         LONG                bgpen=id->BackgroundPen, wfpen=id->WaveformPen;
  1728.         UWORD                *pens = gpr->gpr_GInfo->gi_DrInfo->dri_Pens;
  1729.         WORD                x,y, w,h;
  1730.             
  1731.         gbox = GetAbsGadgetBox( &gpr->gpr_GInfo->gi_Domain, EXTG( o ), FALSE );
  1732.         x = gbox.Left; y = gbox.Top;
  1733.         w = gbox.Width; h = gbox.Height;
  1734.         
  1735.         if( id->ControlPanel )
  1736.         {
  1737.             h -= ( id->TapeDeckHeight + 2 );
  1738.         }
  1739.         
  1740.         if( ( x != SHRT_MAX && y != SHRT_MAX ) && ( w >=16 && h >= 8 ) )
  1741.         {
  1742.             if( gpr->gpr_GInfo->gi_Screen )
  1743.             {
  1744.                 cm = gpr->gpr_GInfo->gi_Screen->ViewPort.ColorMap;
  1745.             
  1746.             }
  1747.                 
  1748.             SetAPen( rp, ( bgpen == -1L ) ? pens[TEXTPEN] : bgpen );
  1749.             RectFill( rp, x,y, w+x-1, h+y-1 );
  1750.  
  1751.             x += 4; y += 2;
  1752.             w -= 8; h -= 4;
  1753.                 
  1754.             SetAPen( rp, ( wfpen == -1L ) ? pens[HIGHLIGHTTEXTPEN] : wfpen );        
  1755.             
  1756.             DrawWaveform( cb, rp, id, x, y, w, h );
  1757.         }
  1758.         
  1759.         if( id->ControlPanel )
  1760.         {
  1761. /*            SetAPen( rp, 4L );
  1762.             RectFill( rp, gbox.Left, gbox.Top+=(gbox.Height-id->TapeDeckHeight-3),
  1763.                 gbox.Left+gbox.Width-1, gbox.Top+id->TapeDeckHeight+1 );*/
  1764.             
  1765.             if( gbox.Height >= ( id->TapeDeckHeight + 2 ) )
  1766.             {
  1767.                 if( gbox.Width >= 201)
  1768.                 {
  1769.                     DoMethodA( (Object *)id->TapeDeckGadget, (Msg) gpr );
  1770.                     
  1771.                     if( gbox.Width >= 220 )
  1772.                     {
  1773.                         DoMethodA( (Object *) id->VolumeSlider, (Msg) gpr );
  1774.                         
  1775.                         if( ! cb->cb_NoGTSlider )
  1776.                         {
  1777.                             Object    *img;
  1778.                             
  1779.                             if( img = NewObject( NULL, FRAMEICLASS,
  1780.                                 IA_Left, id->VolumeSlider->LeftEdge - 4,
  1781.                                 IA_Top,  id->VolumeSlider->TopEdge - 2,
  1782.                                 IA_Width, id->VolumeSlider->Width + 8,
  1783.                                 IA_Height, id->TapeDeckHeight,
  1784.                                 IA_FrameType, FRAME_BUTTON,
  1785.                                 IA_EdgesOnly, TRUE,
  1786.                                 TAG_DONE ) )
  1787.                             {
  1788.                                 DrawImageState( rp, (struct Image *)img, 0,0, IDS_NORMAL, gpr->gpr_GInfo->gi_DrInfo );
  1789.                                 DisposeObject( img );
  1790.                             }    
  1791.                         }
  1792.                     }
  1793.                 }
  1794.             }
  1795.         }
  1796.         
  1797.         if( G( o )->Flags & GFLG_DISABLED )
  1798.         {
  1799.             ULONG patt = 0x11114444;
  1800.             
  1801.             SetAfPt(rp, (UWORD *)&patt, 1);
  1802.             SetAPen( rp, pens[ SHADOWPEN ] );
  1803.             RectFill( rp, gbox.Left, gbox.Top, gbox.Left+gbox.Width-1, gbox.Top+gbox.Height-1 );
  1804.             SetAfPt( rp, NULL, 0L );
  1805.         }
  1806.     }/*
  1807.     else if( gpr->gpr_Redraw == GREDRAW_UPDATE )
  1808.     {
  1809.     }*/
  1810.  
  1811.     return( TRUE );
  1812. }
  1813.  
  1814. /****************************************************************************/
  1815.  
  1816. ULONG __regargs Sound_DRAW( Class *cl, Object *o, struct dtDraw *dtd )
  1817. {
  1818.     struct InstanceData    *id = INST_DATA( cl, o );
  1819.     struct ClassBase        *cb = (struct ClassBase *) cl->cl_UserData;
  1820.     struct RastPort        *rp = dtd->dtd_RPort;
  1821.     struct DrawInfo        *dri;
  1822.     struct Screen            *scr;
  1823.     struct ColorMap        *cm = NULL;
  1824.     UWORD                x = dtd->dtd_Left, y = dtd->dtd_Top, *pens,
  1825.                         w = dtd->dtd_Width, h = dtd->dtd_Height;
  1826.     WORD                bgpen = -1, wfpen = -1;
  1827.     BOOL                freedri;
  1828.     
  1829.     dbug( kprintf( "DTM_DRAW\n" ); )
  1830.  
  1831.     if( scr = id->Screen )
  1832.     {
  1833.         dri = GetScreenDrawInfo( scr );
  1834.         freedri = TRUE;
  1835.     }
  1836.     else 
  1837.     {
  1838.         dri = id->DrawInfo;
  1839.         freedri = FALSE;
  1840.     }
  1841.     
  1842.     if( dri )
  1843.     {
  1844.         pens = dri->dri_Pens;
  1845.         
  1846.         if( scr )
  1847.         {
  1848.             cm = scr->ViewPort.ColorMap;
  1849.             
  1850.             ObtainSemaphoreShared( &cb->cb_LibLock );
  1851.             bgpen = ObtainBestPenA( cm, 
  1852.                 cb->cb_BgCol[0], cb->cb_BgCol[1], cb->cb_BgCol[2], NULL );
  1853.             wfpen = ObtainBestPenA( cm, 
  1854.                 cb->cb_WfCol[0], cb->cb_WfCol[1], cb->cb_WfCol[2], NULL );
  1855.             ReleaseSemaphore( &cb->cb_LibLock );
  1856.         }
  1857.                 
  1858.         SetAPen( rp, ( bgpen == -1L ) ? pens[TEXTPEN] : bgpen );
  1859.         RectFill( rp, x,y, w+x-1, h+y-1 );
  1860.     
  1861.         x += 4; y += 2;
  1862.         w -= 8; h -= 4;
  1863.                 
  1864.         SetAPen( rp, ( wfpen == -1L ) ? pens[HIGHLIGHTTEXTPEN] : wfpen );        
  1865.             
  1866.         DrawWaveform( cb, rp, id, x, y, w, h );
  1867.             
  1868.         if( cm )
  1869.         {
  1870.             ReleasePen( cm, bgpen );
  1871.             ReleasePen( cm, wfpen );
  1872.         }
  1873.             
  1874.         if( freedri )
  1875.         {
  1876.             FreeScreenDrawInfo( scr, dri );
  1877.         }
  1878.     }
  1879.     
  1880.     return( dri != NULL );
  1881. }
  1882.  
  1883. /****************************************************************************/
  1884.  
  1885. ULONG __regargs Sound_HITTEST( Class *cl, Object *o, struct gpHitTest *gpht )
  1886. {
  1887.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  1888.     ULONG                retval = GMR_GADGETHIT;
  1889.     WORD                h = G(o)->Height;
  1890.  
  1891.     dbug( kprintf( "GM_HITTEST\n" ); )
  1892.     
  1893.     if( ! ( G( o )->Flags & GFLG_DISABLED ) )
  1894.     {    
  1895.         /* calculate absolute high */
  1896.         if( G(o)->Flags & GFLG_RELHEIGHT )
  1897.         {
  1898.             h += gpht->gpht_GInfo->gi_Domain.Height;
  1899.         }
  1900.         /* check if one of our members was hit */
  1901.         if( gpht->gpht_Mouse.Y > ( h - ( id->TapeDeckHeight + 3 ) ) )
  1902.         {
  1903.             if( id->ControlPanel )
  1904.             {
  1905.                 struct IBox    domain;
  1906.         
  1907.                 domain = GetAbsGadgetBox( &gpht->gpht_GInfo->gi_Domain, EXTG( o ), FALSE );
  1908.                 
  1909.                 if( ! DoMemberHitTest( &domain, (Object *) id->TapeDeckGadget, gpht ) )
  1910.                 {
  1911.                     if( ! DoMemberHitTest( &domain, (Object *) id->VolumeSlider, gpht ) )
  1912.                     {
  1913.                         retval = 0L;
  1914.                     }
  1915.                 }
  1916.             }
  1917.         }
  1918.         else
  1919.         {
  1920.             /* We were hit, change return code if it was GM_HELPTEST */
  1921.             if( gpht->MethodID == GM_HELPTEST )
  1922.             {
  1923.                 retval = GMR_HELPHIT;
  1924.             }
  1925.         }
  1926.     }
  1927.     else
  1928.     {
  1929.         retval = 0L;
  1930.     }
  1931.     
  1932.     return retval;
  1933. }
  1934.  
  1935. /****************************************************************************/
  1936.  
  1937. ULONG __regargs Sound_HANDLEINPUT( Class *cl, Object *o, struct gpInput *gpi )
  1938. {
  1939.     struct ClassBase        *cb = (struct ClassBase *) cl->cl_UserData;
  1940.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  1941.     struct InputEvent        *ie = gpi->gpi_IEvent;
  1942.     struct DTSpecialInfo    *si = (struct DTSpecialInfo *)G( o )->SpecialInfo;
  1943.     struct IBox            gbox = GetAbsGadgetBox( &gpi->gpi_GInfo->gi_Domain, EXTG( o ), FALSE );
  1944.     ULONG                retval = GMR_MEACTIVE;
  1945.     WORD                mx = gpi->gpi_Mouse.X, my = gpi->gpi_Mouse.Y;
  1946.  
  1947.     dbug( kprintf("GM_GOACTIVE / GM_HANDLEINPUT\n"); )
  1948.     /* no input processing during layout */
  1949.     if( si->si_Flags & DTSIF_LAYOUT )
  1950.     {
  1951.         return GMR_NOREUSE;
  1952.     }
  1953.     
  1954.     /* check if we're hit or one of our members */
  1955.     if( gpi->MethodID == GM_GOACTIVE )
  1956.     {
  1957.         G( o )->Activation |= GACT_ACTIVEGADGET;
  1958.         G( o )->Flags |= GFLG_SELECTED;
  1959.         /* check if mousepointer is over one of our members */
  1960.         if( id->ControlPanel )
  1961.         {
  1962.             if( my > ( gbox.Height - id->TapeDeckHeight - 3 ) )
  1963.             {
  1964.                 struct gpHitTest    gpht = { GM_HITTEST, gpi->gpi_GInfo, mx, my };
  1965.                 
  1966.                 if( gbox.Width >= 201 && DoMemberHitTest( &gbox, (Object *) id->TapeDeckGadget, &gpht ) )
  1967.                 {
  1968.                     id->ActiveMember = id->TapeDeckGadget;
  1969.                 }
  1970.                 else if( gbox.Width >= 220 && DoMemberHitTest( &gbox, (Object *) id->VolumeSlider, &gpht ) )
  1971.                 {
  1972.                     id->ActiveMember = id->VolumeSlider;
  1973.                 }
  1974.                 /* nothing hit ? */
  1975.                 if( ! id->ActiveMember )
  1976.                 {
  1977.                     retval = GMR_NOREUSE;
  1978.                 }
  1979.             }
  1980.         }
  1981.     }
  1982.     /* pass input to the active member ( if there's one ) */
  1983.     if( id->ActiveMember )
  1984.     {
  1985.         struct IBox    domain = gbox;        
  1986.         
  1987.         gbox = GetAbsGadgetBox( &gpi->gpi_GInfo->gi_Domain, EXTG( id->ActiveMember ), FALSE );
  1988.         
  1989.         (gpi -> gpi_Mouse . X) -= ((gbox . Left) - (domain . Left));
  1990.         (gpi -> gpi_Mouse . Y) -= ((gbox . Top) - (domain . Top));
  1991.         
  1992.         if( ( retval = DoMethodA( (Object *) id->ActiveMember, (Msg) gpi ) ) & GMR_VERIFY )
  1993.         {    /* tapedeck.gadget doesn't send OM_UPDATE :( */
  1994.             if( id->ActiveMember == id->TapeDeckGadget )
  1995.             {
  1996.                 if( ie->ie_Code == IECODE_LBUTTON )
  1997.                 {
  1998.                     ULONG            stm = 0L;
  1999.                     
  2000.                     dbug( kprintf( "TapeDeck ICSPECIAL_CODE: %04lx\n", *gpi->gpi_Termination ); )
  2001.                     
  2002.                     if( *gpi->gpi_Termination & 0x1000 )
  2003.                     {
  2004.                         stm = STM_PAUSE;
  2005.                     }
  2006.                     else
  2007.                     {
  2008.                         switch( *gpi->gpi_Termination )
  2009.                         {
  2010.                             case BUT_PLAY:
  2011.                                 stm = STM_PLAY;
  2012.                             break;
  2013.                             
  2014.                             case BUT_STOP:
  2015.                                 stm = STM_STOP;
  2016.                             break;
  2017.                         }
  2018.                     }
  2019.                     
  2020.                     if( stm )
  2021.                     {    
  2022.                         CoerceMethod( cl, o, DTM_TRIGGER, NULL, stm, NULL );
  2023.                     }
  2024.                 }
  2025.             }
  2026.         }
  2027.         
  2028.         (gpi -> gpi_Mouse . X) += ((gbox . Left) - (domain . Left));
  2029.         (gpi -> gpi_Mouse . Y) += ((gbox . Top) - (domain . Top));
  2030.     }
  2031.     /* we're hit */
  2032.     else if( retval == GMR_MEACTIVE )
  2033.     {
  2034.         while( ie )
  2035.         {
  2036.             if( ie->ie_Class == IECLASS_RAWMOUSE )
  2037.             {
  2038.                 /* test for mark mode */
  2039.                 if( si->si_Flags & DTSIF_DRAGSELECT )
  2040.                 {
  2041.                     struct RastPort     *rp;
  2042.                     WORD            mx = gpi->gpi_Mouse.X, x, y, w, h;
  2043.         
  2044.                     x = gbox.Left; y = gbox.Top + 2;
  2045.                     w = gbox.Width - 8; h = gbox.Height - 4;
  2046.                     
  2047.                     if( id->ControlPanel )
  2048.                     {
  2049.                         h -= ( id->TapeDeckHeight + 2 );
  2050.                     }
  2051.                     
  2052.                     if( mx > (w+3) )
  2053.                     {
  2054.                         mx = w+3;
  2055.                     }
  2056.                     else if( mx < 4 )
  2057.                     {
  2058.                         mx = 4;
  2059.                     }
  2060.                     
  2061.                     if( id->MarkMode )
  2062.                     {                    
  2063.                         if( id->MaxX != (x+mx) )
  2064.                         {
  2065.                             if( rp = ObtainGIRPort( gpi->gpi_GInfo ) )
  2066.                             {
  2067.                                 UWORD    minX, maxX;
  2068.                                 
  2069.                                 SetDrMd( rp, COMPLEMENT );
  2070.                                 
  2071.                                 minX = id->MinX;
  2072.                                 maxX = id->MaxX;
  2073.                                 
  2074.                                 if( minX > maxX )
  2075.                                 {
  2076.                                     maxX = minX;
  2077.                                     minX = id->MaxX;
  2078.                                 }
  2079.                                 //WaitTOF();
  2080.                                 RectFill( rp, minX, y, maxX, y+h-1 );
  2081.                                 
  2082.                                 minX = id->MinX;
  2083.                                 maxX =
  2084.                                 id->MaxX = x + mx;
  2085.                                 
  2086.                                 if( minX > maxX )
  2087.                                 {
  2088.                                     maxX = minX;
  2089.                                     minX = id->MaxX;                        
  2090.                                 }
  2091.                                 //WaitTOF();
  2092.                                 RectFill( rp, minX, y, maxX, y+h-1 );
  2093.                                 /* fixes a bug (?) of tapedeck.gadget */
  2094.                                 SetDrMd( rp, JAM1 );
  2095.                                 
  2096.                                 ReleaseGIRPort( rp );
  2097.                             }
  2098.                         }
  2099.                     }
  2100.                     /* start mark mode */
  2101.                     else if( ie->ie_Code == IECODE_LBUTTON )
  2102.                     {    
  2103.                         if( id->MinX != ~0L )
  2104.                         {
  2105.                             DoMethod( o, DTM_CLEARSELECTED, (ULONG) gpi->gpi_GInfo );
  2106.                         }
  2107.                         
  2108.                         id->MarkMode = TRUE;
  2109.                         
  2110.                         id->MinX =
  2111.                         id->MaxX = x + mx;
  2112.                     }
  2113.                 }
  2114.                 /* not in mark mode - start or stop playing */
  2115.                 else if( ie->ie_Code == IECODE_LBUTTON )
  2116.                 {
  2117.                     struct timeval        tv = gpi->gpi_IEvent->ie_TimeStamp;
  2118.                     STATIC ULONG    stm[] = { STM_PLAY, STM_STOP };
  2119.                     
  2120.                     CoerceMethod( cl, o, DTM_TRIGGER, NULL, stm[ DoubleClick( id->LastClick.tv_secs, id->LastClick.tv_micro, tv.tv_secs, tv.tv_micro ) ], 0L );
  2121.                     
  2122.                     id->LastClick = tv;
  2123.                 }
  2124.             
  2125.                 if( ie->ie_Code == SELECTUP )
  2126.                 {
  2127.                     retval = GMR_NOREUSE;
  2128.                     break;
  2129.                 }
  2130.             }
  2131.         
  2132.             ie = ie->ie_NextEvent;
  2133.         }
  2134.     }
  2135.     
  2136.     return( retval );
  2137. }
  2138.  
  2139. /****************************************************************************/
  2140.  
  2141. ULONG __regargs Sound_GOINACTIVE( Class *cl, Object *o, struct gpGoInactive *gpgi )
  2142. {
  2143.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  2144.     struct ClassBase        *cb = (struct ClassBase *) cl->cl_UserData;
  2145.     
  2146.     DoSuperMethodA( cl, o, (Msg) gpgi );
  2147.     
  2148.     dbug( kprintf("GOINACTIVE\n"); )
  2149.     
  2150.     if( id->ActiveMember )
  2151.     {
  2152.         DoMethodA( (Object *) id->ActiveMember, (Msg) gpgi );
  2153.         id->ActiveMember = NULL;
  2154.     }
  2155.     
  2156.     id->MarkMode = FALSE;
  2157.     
  2158.     G( o )->Activation &= ~GACT_ACTIVEGADGET;
  2159.     G( o )->Flags &= ~GFLG_SELECTED;
  2160.     
  2161.     return 0L;
  2162. }
  2163.  
  2164. /****************************************************************************/
  2165.  
  2166. ULONG __regargs Sound_TRIGGER( Class *cl, Object *o, struct dtTrigger *dtt )
  2167. {
  2168.     struct ClassBase        *cb = (struct ClassBase *)cl->cl_UserData;
  2169.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  2170.     APTR                data = NULL;
  2171.     ULONG                cmd = ~0L;
  2172.  
  2173.     dbug( kprintf("DTM_TRIGGER\n"); )
  2174.  
  2175.     switch( dtt->dtt_Function )
  2176.     {
  2177.         case STM_PLAY:
  2178.             dbug( kprintf( "STM_PLAY\n" ); )
  2179.             cmd = COMMAND_PLAY;
  2180.             data = (APTR) id;
  2181.         break;
  2182.         
  2183.         case STM_STOP:
  2184.             dbug( kprintf( "STM_STOP\n" ); )
  2185.             cmd = COMMAND_STOP;
  2186.         break;
  2187.         
  2188.         case STM_PAUSE:
  2189.             dbug( kprintf( "STM_PAUSE\n" ); )
  2190.             cmd = COMMAND_PAUSE;
  2191.         break;
  2192.     }
  2193.         
  2194.     if( cmd != ~0L )
  2195.     {
  2196.         SendObjectMsg( id, cmd, data );
  2197.     }
  2198.     
  2199.     return 0L;
  2200. }
  2201.  
  2202. /****************************************************************************/
  2203. // "stolen" from embeddt
  2204. ULONG __regargs DoMemberHitTest( struct IBox *domain, Object *member, struct gpHitTest *gpht )
  2205. {
  2206.     struct GadgetInfo     *gi = gpht -> gpht_GInfo;
  2207.     struct IBox        gbox;
  2208.     ULONG                  retval = 0L;
  2209.  
  2210.     gbox = GetAbsGadgetBox( &gi->gi_Domain, EXTG( member ), (BOOL) ( gpht -> MethodID == GM_HELPTEST ) );
  2211.  
  2212.     (gpht->gpht_Mouse.X) -= ((gbox.Left) - (domain->Left));
  2213.     (gpht->gpht_Mouse.Y) -= ((gbox.Top)  - (domain->Top));
  2214.     
  2215.     /* Mouse coordinates must be inside members's select box */
  2216.     if(    ((gpht->gpht_Mouse . X) >= 0) &&
  2217.         ((gpht->gpht_Mouse . Y) >= 0) &&
  2218.         ((gpht->gpht_Mouse . X) <= (gbox.Width)) &&
  2219.         ((gpht->gpht_Mouse . Y) <= (gbox.Height)) )
  2220.     {
  2221.         retval = DoMethodA( member, (Msg)gpht );
  2222.     }
  2223.     
  2224.     (gpht->gpht_Mouse.X) += ((gbox.Left) - (domain->Left));
  2225.     (gpht->gpht_Mouse.Y) += ((gbox.Top)  - (domain->Top));
  2226.     
  2227.     return( retval );
  2228. }
  2229.  
  2230. /****************************************************************************/
  2231.  
  2232. struct IBox __regargs GetAbsGadgetBox( struct IBox *domain, struct ExtGadget *g, BOOL useBounds )
  2233. {
  2234.     struct IBox retbox = { 0, 0, 0, 0 };
  2235.  
  2236.     if( domain && g )
  2237.     {
  2238.         if( ((g->MoreFlags) & GMORE_BOUNDS) && useBounds )
  2239.         {
  2240.             retbox = *((struct IBox *)(&(g->BoundsLeftEdge)));
  2241.         }
  2242.         else
  2243.         {
  2244.             retbox = *(GADGET_BOX( g ));
  2245.         }
  2246.     
  2247.         if( (g->Flags) & GFLG_RELBOTTOM )
  2248.         {
  2249.             (retbox.Top) += ((domain->Top) + (domain->Height));
  2250.         }
  2251.     
  2252.         if( (g->Flags) & GFLG_RELRIGHT )
  2253.         {
  2254.             (retbox.Left) += ((domain->Left) + (domain->Width));
  2255.         }
  2256.     
  2257.         if( (g->Flags) & GFLG_RELWIDTH )
  2258.         {
  2259.             (retbox.Width) += (domain->Width);
  2260.         }
  2261.     
  2262.         if( (g->Flags) & GFLG_RELHEIGHT )
  2263.         {
  2264.             (retbox.Height) += (domain->Height);
  2265.         }
  2266.     }
  2267.     
  2268.     return( retbox );
  2269. }
  2270.  
  2271. /****************************************************************************/
  2272.  
  2273. void __regargs makeqtab( BYTE *qtab )
  2274. {
  2275.     LONG i;
  2276.     
  2277.     for( i=0; i < 512; i++ )
  2278.     {
  2279.         qtab[i] = 0;
  2280.     }
  2281.     
  2282.     for ( i = 1; i < 16; i++ )
  2283.     {
  2284.         LONG    j = 256 + fibtab[i],
  2285.                 k = 256 + fibtab[i-1];
  2286.                 
  2287.         if( fibtab[i] < 0 ) 
  2288.         {
  2289.             while( j > k )
  2290.             {
  2291.                 qtab[j--] = i;
  2292.             }
  2293.         } 
  2294.         else 
  2295.         {
  2296.             while( j < 512 )
  2297.             {
  2298.                 qtab[j++] = i;
  2299.             }
  2300.         }
  2301.     }
  2302. }
  2303.  
  2304. /****************************************************************************/
  2305.  
  2306. LONG __regargs WriteChunk( struct ClassBase *cb, struct IFFHandle *iff, ULONG type, ULONG id, APTR data, ULONG size )
  2307. {
  2308.     LONG    err;
  2309.     
  2310.     if( ! ( err = PushChunk( iff, type, id, size ) ) )
  2311.     {
  2312.         if( ( err = WriteChunkBytes( iff, data, size ) ) == size )
  2313.         {
  2314.             err = PopChunk( iff );
  2315.         }
  2316.     }
  2317.     
  2318.     return err;
  2319. }
  2320.  
  2321. /****************************************************************************/
  2322.  
  2323. LONG __regargs WriteAIFF( struct ClassBase *cb, Object *o, struct IFFHandle *iff, struct InstanceData *id )
  2324. {
  2325.         LONG    err;
  2326.     
  2327.     if( ! ( err = PushChunk( iff, ID_AIFF, ID_FORM, IFFSIZE_UNKNOWN ) ) )
  2328.     {
  2329.         CommonChunk    common;
  2330.         UBYTE            sampleType = id->SampleType;
  2331.         ULONG            sampleLength = id->SampleLength;
  2332.         BYTE            *sample = id->Sample;
  2333.  
  2334.         if( id->StartSample != ~0L )
  2335.         {
  2336.             sample = &sample[ UMult32( id->StartSample, bytesPerPoint[ sampleType ] ) ];
  2337.             sampleLength = id->EndSample - id->StartSample;
  2338.         }
  2339.  
  2340.         common.numChannels = ( sampleType & 1 ) + 1;
  2341.         common.numSampleFrames = sampleLength;
  2342.         common.sampleSize = ( sampleType >= SDTST_M16S ) ? 16 : 8;
  2343.         ulong2extended( id->Frequency, &common.sampleRate );
  2344.             
  2345.         if( ! ( err = WriteChunk( cb, iff, ID_AIFF, ID_COMM, &common, sizeof( common ) ) ) )
  2346.         {        
  2347.             SampledSoundHeader    ssnd = { 0L, 0L };
  2348.  
  2349.             if( ! ( err = PushChunk( iff, ID_AIFF, ID_SSND, IFFSIZE_UNKNOWN ) ) )
  2350.             {
  2351.                 if( ( err = WriteChunkBytes( iff, &ssnd, sizeof( ssnd ) ) ) == sizeof( ssnd ) )
  2352.                 {                
  2353.                     ULONG    bytes = UMult32( sampleLength, bytesPerPoint[ sampleType ] );
  2354.  
  2355.                     if( ( err = WriteChunkBytes( iff, sample, bytes ) ) == bytes )
  2356.                     {
  2357.                         err = PopChunk( iff );
  2358.                     }
  2359.                 }
  2360.             }
  2361.         }
  2362.         
  2363.         if( ! err )
  2364.         {
  2365.             err = PopChunk( iff );
  2366.         }
  2367.     }
  2368.     
  2369.     return( err );
  2370. }
  2371.  
  2372. /****************************************************************************/
  2373.  
  2374. LONG __regargs WriteSVX( struct ClassBase *cb, Object *o, struct IFFHandle *iff, struct InstanceData *id )
  2375. {
  2376.     UBYTE    sampletype = id->SampleType, bps = ( sampletype >= SDTST_M16S ? 2 : 1 );
  2377.     BOOL    stereo = IsStereo( id->SampleType );
  2378.     LONG    err, type = ( sampletype >= SDTST_M16S ? ID_16SV : ID_8SVX );
  2379.     ULONG    sampleLength = id->SampleLength;
  2380.     BYTE    *sample = id->Sample;
  2381.     struct VoiceHeader    vhdr;
  2382.  
  2383.     CopyMem( &id->VoiceHeader, &vhdr, sizeof( vhdr ) );
  2384.     vhdr.vh_Compression = ( ( id->VoiceHeader.vh_Compression == CMP_FIBDELTA ) || ( cb->cb_Compress ) ) && ( sampletype <= SDTST_S8S );
  2385.                             
  2386.     if( id->StartSample != ~0L )
  2387.     {
  2388.         sample = &sample[ UMult( id->StartSample, bytesPerPoint[ sampletype ] ) ];
  2389.         sampleLength = id->EndSample - id->StartSample;
  2390.         vhdr.vh_OneShotHiSamples = sampleLength;
  2391.         vhdr.vh_RepeatHiSamples = 0L;
  2392.     }
  2393.     
  2394.     if( ! ( err = PushChunk( iff, type, ID_FORM, IFFSIZE_UNKNOWN ) ) )
  2395.     {
  2396.         if( ! ( err = WriteChunk( cb, iff, type, ID_VHDR, &vhdr, sizeof( vhdr ) ) ) )
  2397.         {
  2398.             struct ObjectData
  2399.             {
  2400.                 ULONG    attr;
  2401.                 ULONG    id;
  2402.                 STRPTR    data;
  2403.             } ObjData[] = { 
  2404.                 DTA_ObjName, ID_NAME, NULL, 
  2405.                 DTA_ObjAnnotation, ID_ANNO, NULL,
  2406.                 DTA_ObjAuthor, ID_AUTH, NULL,
  2407.                 DTA_ObjCopyright, ID_Copyright, NULL,
  2408.                 DTA_ObjVersion, ID_FVER, NULL,
  2409.                 NULL 
  2410.             };
  2411.             LONG    i;
  2412.             
  2413.             for( i = 0; ObjData[i].attr; i++ )
  2414.             {
  2415.                 struct ObjectData    *od = &ObjData[i];
  2416.                 
  2417.                 if( GetDTAttrs( o, od->attr, (ULONG) &od->data, TAG_DONE ) && od->data )
  2418.                 {
  2419.                     if( ( err = WriteChunk( cb, iff, type, od->id, od->data, strlen( od->data ) ) ) )
  2420.                     {
  2421.                         break;
  2422.                     }
  2423.                 }
  2424.             }
  2425.             
  2426.             if( ! err )
  2427.             {
  2428.                 if( stereo )
  2429.                 {
  2430.                     ULONG    chan = 6L;
  2431.                     err = WriteChunk( cb, iff, type, ID_CHAN, &chan, sizeof( ULONG ) );
  2432.                 }
  2433.                 else
  2434.                 {
  2435.                     ULONG    pan = 0x10000 - id->Panning;
  2436.                     err = WriteChunk( cb, iff, type, ID_PAN, &pan, sizeof( ULONG ) );
  2437.                 }
  2438.             }
  2439.             
  2440.             if( ! err )
  2441.             {
  2442.                 if( vhdr.vh_Compression == CMP_FIBDELTA )
  2443.                 {
  2444.                     BYTE    *qtab, *buf;
  2445.                     LONG    buffersize;
  2446.                     
  2447.                     buffersize = sampleLength;
  2448.                                             
  2449.                     while( ! ( buf = AllocVec( buffersize + 512L, MEMF_PUBLIC ) ) )
  2450.                     {
  2451.                         if( ( buffersize /= 2 ) < 1024L )
  2452.                         {
  2453.                             break;
  2454.                         }
  2455.                     }
  2456.                     
  2457.                     if( buf )
  2458.                     {
  2459.                         if( ! ( err = PushChunk( iff, type, ID_BODY, IFFSIZE_UNKNOWN ) ) )
  2460.                         {
  2461.                             LONG    i;
  2462.  
  2463.                             qtab = &buf[buffersize];
  2464.                             makeqtab( qtab );
  2465.                             
  2466.                             for( i = 0; i < (stereo?2:1) && !err; i++ )
  2467.                             {
  2468.                                 LONG    length = sampleLength, samples = 0L;
  2469.                                 BYTE    c0 = 0, *src = &sample[i], add = stereo?2:1;
  2470.                                 UBYTE    o, x = 1; 
  2471.                                 
  2472.                                 if( length & 1 )
  2473.                                 {
  2474.                                     c0 = *src++;
  2475.                                     length--;
  2476.                                 }
  2477.  
  2478.                                 buf[ 0 ] = 0;
  2479.                                 buf[ 1 ] = c0;
  2480.                                 samples += 2;
  2481.                                 
  2482.                                 while( length-- )
  2483.                                 {    
  2484.                                     UBYTE    n;
  2485.                                         
  2486.                                     c0 += fibtab[ n = qtab[256+(*src-c0)] ];
  2487.                                     
  2488.                                     src+=add;
  2489.                                     
  2490.                                     if( x^=1 )
  2491.                                     {
  2492.                                         buf[samples++] = o | n;
  2493.                                     }
  2494.                                     else
  2495.                                     {
  2496.                                         o = n << 4;
  2497.                                     }
  2498.                                         
  2499.                                     if( samples == buffersize || length == 0L )
  2500.                                     {
  2501.                                         if( ( err = WriteChunkBytes( iff, buf, samples ) ) != samples )
  2502.                                         {
  2503.                                             break;
  2504.                                         }
  2505.                                         err = samples = 0L;
  2506.                                     }
  2507.                                 }
  2508.                             }
  2509.                             
  2510.                             if( ! err )
  2511.                             {
  2512.                                 err = PopChunk( iff );
  2513.                             }
  2514.                         }
  2515.                         
  2516.                         FreeVec( buf );
  2517.                     }
  2518.                     else
  2519.                     {
  2520.                         err = ERROR_NO_FREE_STORE;
  2521.                     }
  2522.                 }                    
  2523.                 /*
  2524.                 ** write uncompressed svx file
  2525.                 */                    
  2526.                 else
  2527.                 {
  2528.                     /*
  2529.                     **    create a stereo BODY
  2530.                     */
  2531.                     if( stereo )
  2532.                     {
  2533.                         if( ! ( err = PushChunk( iff, type, ID_BODY, IFFSIZE_UNKNOWN ) ) )
  2534.                         {                                
  2535.                             BYTE    *buf;
  2536.                             LONG    bufsize = sampleLength;
  2537.                             
  2538.                             while( ! ( buf = AllocVec( UMult( bufsize, bps ), MEMF_PUBLIC ) ) )
  2539.                             {
  2540.                                 if( ( bufsize /= 2 ) < 1024L )
  2541.                                 {
  2542.                                     break;
  2543.                                 }
  2544.                             }
  2545.                             
  2546.                             if( buf )
  2547.                             {                                    
  2548.                                 LONG    i;
  2549.                                 
  2550.                                 for( i = 0; i < 2 && ! err; i++, sample+=bps )
  2551.                                 {                                    
  2552.                                     LONG    samples = bufsize, length = sampleLength;
  2553.                                     BYTE    *src = sample;
  2554.                                     
  2555.                                     while( length )
  2556.                                     {
  2557.                                         ULONG    bytes = UMult( samples, bps );
  2558.                                         
  2559.                                         if( sampletype == SDTST_S16S )
  2560.                                         {
  2561.                                             WORD    *dst = (WORD *)buf,
  2562.                                                     *src_p = (WORD *)src;
  2563.                                             LONG    c;
  2564.                                             
  2565.                                             for( c = samples; c; c--, src_p+=2 )
  2566.                                             {
  2567.                                                 *dst++ = *src_p;
  2568.                                             }
  2569.                                             
  2570.                                             src = (BYTE *) src_p;
  2571.                                         }
  2572.                                         else
  2573.                                         {
  2574.                                             BYTE    *dst = buf;
  2575.                                             LONG    c;
  2576.                                             
  2577.                                             for( c = samples; c; c--, src+=2 )
  2578.                                             {
  2579.                                                 *dst++ = *src;
  2580.                                             }
  2581.                                         }
  2582.                                         
  2583.                                         if( ( err = WriteChunkBytes( iff, buf, bytes ) ) != bytes )
  2584.                                         {
  2585.                                             break;
  2586.                                         }
  2587.                                         
  2588.                                         if( (length-=samples) < samples )
  2589.                                         {
  2590.                                             samples = length;
  2591.                                         }
  2592.                                         
  2593.                                         err = 0L;
  2594.                                     }
  2595.                                 }
  2596.                                 
  2597.                             }
  2598.                             else
  2599.                             {
  2600.                                 err = ERROR_NO_FREE_STORE;
  2601.                             }
  2602.                             
  2603.                             if( ! err )
  2604.                             {
  2605.                                 err = PopChunk( iff );
  2606.                             }
  2607.                         }
  2608.                     }
  2609.                     /*
  2610.                     **    write uncompressed mono sample
  2611.                     */
  2612.                     else
  2613.                     {
  2614.                         err = WriteChunk( cb, iff, type, ID_BODY, sample, UMult( sampleLength, bps ) );
  2615.                     }
  2616.                 }
  2617.             }
  2618.         }
  2619.             
  2620.         if( ! err )
  2621.         {
  2622.             err = PopChunk( iff );
  2623.         }
  2624.     }
  2625.     
  2626.     return( err );
  2627. }
  2628.  
  2629. /****************************************************************************/
  2630.  
  2631. ULONG __regargs Sound_WRITE( Class *cl, Object *o, struct dtWrite *dtw )
  2632. {
  2633.     struct ClassBase        *cb = (struct ClassBase *)cl->cl_UserData;
  2634.     struct InstanceData    *id = (struct InstanceData *) INST_DATA( cl, o );
  2635.     struct IFFHandle        *iff;
  2636.     struct SignalSemaphore    *lock = &((struct DTSpecialInfo *)G( o )->SpecialInfo)->si_Lock;
  2637.     LONG                err = 0L;
  2638.     
  2639.     dbug( kprintf( "DTM_WRITE / DTM_COPY\n" ); )
  2640.     
  2641.     ObtainSemaphoreShared( &cb->cb_LibLock );
  2642.     
  2643.     if( id->Sample )
  2644.     {
  2645.         ObtainSemaphoreShared( lock );
  2646.             
  2647.         if( iff = AllocIFF() )
  2648.         {
  2649.             if( dtw->MethodID == DTM_WRITE )
  2650.             {
  2651.                 dbug( kprintf( "DTWM_RAW\n" ); )
  2652.                 
  2653.                 if( iff->iff_Stream = dtw->dtw_FileHandle )
  2654.                 {
  2655.                     InitIFFasDOS( iff );
  2656.                 }
  2657.                 else
  2658.                 {
  2659.                     dbug( kprintf( "NULL filehandle\n"); )
  2660.                     err = ERROR_INVALID_LOCK;
  2661.                 }
  2662.             }
  2663.             else
  2664.             {
  2665.                 dbug( kprintf( "DTM_COPY\n" ); )
  2666.                 
  2667.                 if( iff->iff_Stream = (ULONG) OpenClipboard( PRIMARY_CLIP ) )
  2668.                 {
  2669.                     InitIFFasClip( iff );
  2670.                 }
  2671.                 else
  2672.                 {
  2673.                     dbug( kprintf( "Cant open clipboard\n" ); )
  2674.                     err = ERROR_OBJECT_IN_USE;
  2675.                 }
  2676.             }
  2677.     
  2678.             if( ! err )
  2679.             {
  2680.                 if( err = OpenIFF( iff, IFFF_WRITE ) )
  2681.                 {
  2682.                     err = ifferr2doserr[-err-1];
  2683.                     dbug( kprintf( "OpenIFF() failed\n" ); )
  2684.                 }
  2685.             }
  2686.         }
  2687.         else
  2688.         {
  2689.             err = ERROR_NO_FREE_STORE;
  2690.             dbug( kprintf( "AllocIFF failed\n" ); )
  2691.         }
  2692.  
  2693.         if( ! err )
  2694.         {
  2695.             dbug( kprintf( "Everything fine so far ...\n" ); )
  2696.             
  2697.             if( id->SampleType >= SDTST_M16S && cb->cb_AIFF )
  2698.             {
  2699.                 err = WriteAIFF( cb, o, iff, id );
  2700.             }
  2701.             else
  2702.             {
  2703.                 err = WriteSVX( cb, o, iff, id );
  2704.             }
  2705.         
  2706.             if( err < 0L )
  2707.             {
  2708.                 err = ifferr2doserr[-err-1];
  2709.             }
  2710.         }
  2711.         else
  2712.         {
  2713.             dbug( kprintf( "Something failed\n" ); )
  2714.         }
  2715.         
  2716.         dbug( kprintf( "closing iff stream\n" ); )
  2717.             
  2718.         CloseIFF( iff );
  2719.             
  2720.         if( dtw->MethodID == DTM_COPY )
  2721.         {
  2722.             CloseClipboard( (struct ClipboardHandle *)iff->iff_Stream );
  2723.         }
  2724.             
  2725.         FreeIFF( iff );
  2726.  
  2727.         ReleaseSemaphore( lock );
  2728.     }
  2729.     else
  2730.     {
  2731.         err = ERROR_REQUIRED_ARG_MISSING;
  2732.     }
  2733.     
  2734.     ReleaseSemaphore( &cb->cb_LibLock );
  2735.     
  2736.     SetIoErr( err );
  2737.     return( err ? FALSE : TRUE );
  2738. }
  2739.  
  2740. /****************************************************************************/
  2741.  
  2742. /*
  2743. **    test if dblscan screenmode
  2744. **    taken from the ahi paula driver by Martin Blom
  2745. */
  2746. #if 0
  2747. BOOL Is31Khz( struct ClassBase *cb )
  2748. {
  2749.     BOOL    ret = FALSE;
  2750.     
  2751.     /* check for ocs */
  2752. #ifdef __MAXON__
  2753.     extern struct Library    *GfxBase, *IntuitionBase;
  2754.  
  2755.     if( ((struct GfxBase *)GfxBase)->ChipRevBits0 & ( GFXF_HR_DENISE|GFXF_AA_LISA ) )
  2756. #else
  2757. #undef GfxBase
  2758.     if( ((struct GfxBase *)cb->cb_GfxBase)->ChipRevBits0 & ( GFXF_HR_DENISE|GFXF_AA_LISA ) )
  2759. #define GfxBase    cb->cb_GfxBase
  2760. #endif
  2761.     {
  2762.         ULONG    lock, modeid;
  2763.         
  2764.         lock = LockIBase( 0L );
  2765. #ifdef __MAXON__
  2766.         modeid = GetVPModeID( & ((struct IntuitionBase *)IntuitionBase)->FirstScreen->ViewPort );
  2767. #else
  2768. #undef IntuitionBase
  2769.         modeid = GetVPModeID( & ((struct IntuitionBase *)cb->cb_IntuitionBase)->FirstScreen->ViewPort );
  2770. #define IntuitionBase    cb->cb_IntuitionBase
  2771. #endif
  2772.         UnlockIBase( lock );
  2773.         
  2774.         /* gfxboard  */
  2775.         if( modeid & 0x40000000 )
  2776.         {
  2777.             Forbid();
  2778.             if( FindTask( "Picasso96" ) )
  2779.             {
  2780.                 UBYTE    buf[16];
  2781.                 
  2782.                 Permit();
  2783.                 
  2784.                 if( GetVar( "Picasso96/AmigaVideo", buf, sizeof( buf ), GVF_GLOBAL_ONLY ) )
  2785.                 {
  2786.                     if( ! Strnicmp( buf, "31Khz" , 5L ) )
  2787.                     {
  2788.                         ret = TRUE;
  2789.                     }
  2790.                 }
  2791.             }
  2792.             else
  2793.             {
  2794. #ifdef __MAXON__
  2795.                 struct copinit    *ci = ((struct GfxBase *)GfxBase)->copinit;
  2796. #else
  2797. #undef GfxBase
  2798.                 struct copinit    *ci = ((struct GfxBase *)cb->cb_GfxBase)->copinit;
  2799. #define GfxBase    cb->cb_GfxBase
  2800. #endif
  2801.                 Permit();
  2802.                 
  2803.                 if( ( ci->fm0[ 0 ] != 0x01fc ) || ( ci->fm0[ 1 ] & 0xc000 ) )
  2804.                 {
  2805.                     ret = TRUE;
  2806.                 }
  2807.             }
  2808.         }
  2809.         /* native screen */
  2810.         else
  2811.         {
  2812.             struct MonitorInfo    moni;
  2813.             
  2814.             if( GetDisplayInfoData( NULL, (UBYTE *) &moni, sizeof( moni ), DTAG_MNTR, modeid ) )
  2815.             {
  2816.                 if( moni.TotalColorClocks * moni.TotalRows / ( 2 * ( moni.TotalRows - moni.MinRow + 1 ) ) <= 64 )
  2817.                 {
  2818.                     ret = TRUE;
  2819.                 }
  2820.             }
  2821.         }
  2822.     }
  2823.     
  2824.     return ret;
  2825. }
  2826. #endif
  2827. /****************************************************************************/
  2828.  
  2829. void __regargs CalcPanVol( UWORD overall, ULONG pan, UWORD *leftvol, UWORD *rightvol )
  2830. {
  2831.     pan = ( pan << 6 ) >> 16;
  2832.     *rightvol = pan ? overall / ( 64 / pan ) : 0;
  2833.     *leftvol = overall - *rightvol;
  2834. }
  2835.  
  2836. /****************************************************************************/
  2837.  
  2838. void __regargs RemoveRequest( struct IORequest *ior )
  2839. {
  2840. #ifndef __MAXON__
  2841. #undef SysBase
  2842. struct Library    *SysBase = (*(struct Library **)4L);
  2843. #endif
  2844.     struct Node    *ln, *succ;
  2845.     
  2846.     Disable();
  2847.     for(    ln = ior->io_Message.mn_ReplyPort->mp_MsgList.lh_Head;
  2848.             succ = ln->ln_Succ; ln = succ )
  2849.     {
  2850.         if( ln == &ior->io_Message.mn_Node )
  2851.         {
  2852.             Remove( ln );
  2853.             SetSignal( 0L, 1L << ior->io_Message.mn_ReplyPort->mp_SigBit );
  2854.             break;
  2855.         }
  2856.     }
  2857.     Enable();
  2858. #ifndef __MAXON__
  2859. #undef SysBase
  2860. #define SysBase    cb->cb_SysBase
  2861. #endif
  2862. }
  2863.  
  2864. /****************************************************************************/
  2865.  
  2866. #define LEFT_CHANNEL_0    1
  2867. #define RIGHT_CHANNEL_1    2
  2868. #define RIGHT_CHANNEL_2    4
  2869. #define LEFT_CHANNEL_3    8
  2870. #define MAX_SAMPLE        131072
  2871. #define MAX_SAMPLE_RATE    28867
  2872. #define LEFT_MASK        (LEFT_CHANNEL_0|LEFT_CHANNEL_3)
  2873. #define RIGHT_MASK        (RIGHT_CHANNEL_1|RIGHT_CHANNEL_2)
  2874.  
  2875. enum {
  2876.     AUDIO_CONTROL,
  2877.     AUDIO_LEFT,
  2878.     AUDIO_LEFT2,
  2879.     AUDIO_RIGHT,
  2880.     AUDIO_RIGHT2,
  2881.     NUM_REQUESTS
  2882. };
  2883.  
  2884. /****************************************************************************/
  2885.  
  2886. void __regargs SetTDMode( struct ClassBase *cb, struct InstanceData *id, ULONG mode )
  2887. {
  2888.     if( id->ControlPanel )
  2889.     {
  2890.         ULONG    oldmode = mode;
  2891.         
  2892.         ObtainSemaphoreShared( &id->Lock );
  2893.  
  2894.         /* avoid deadlocks */
  2895.         GetAttr( TDECK_Mode, id->TapeDeckGadget, &oldmode );
  2896.         if( oldmode != mode )
  2897.         {
  2898.             SetGadgetAttrs( id->TapeDeckGadget, id->Window, id->Requester,
  2899.                 TDECK_Mode, mode, TAG_DONE );
  2900.         }
  2901.         
  2902.         ReleaseSemaphore( &id->Lock );
  2903.     }
  2904. }
  2905.  
  2906. /****************************************************************************/
  2907.  
  2908. void PlayerProc( void )
  2909. {
  2910. #ifndef __MAXON__
  2911. #undef SysBase
  2912.     struct Library        *SysBase = *(struct Library **)4L;
  2913. #endif
  2914.     struct Process    *pr = (struct Process *) FindTask( NULL );
  2915.     struct MsgPort    *mp, *mpaudio = NULL;
  2916.     struct IOAudio    *ioaudio[NUM_REQUESTS] = { };
  2917.     struct ClassBase    *cb;
  2918.     struct InstanceData *id;
  2919.     LONG            numChAllocated, samples, buffersize, length, cycles, 
  2920.                     loops, audiompmsk, mpmsk;
  2921.     BOOL            releaseAudio = FALSE, restart, paused = FALSE;
  2922.     BYTE            *sample, *buffer[4] = {};
  2923.     
  2924.     mp = &pr->pr_MsgPort;
  2925.     mpmsk = 1L << mp->mp_SigBit;
  2926.     
  2927.     dbug( kprintf("child process launched\n"); )
  2928.     
  2929.     for( ;; )
  2930.     {
  2931.         struct ObjectMsg    *msg;
  2932.         LONG            rcv;
  2933.         
  2934.         rcv = Wait( mpmsk | audiompmsk );
  2935.         
  2936.         if( rcv & mpmsk )
  2937.         {
  2938.             while( msg = (struct ObjectMsg *) GetMsg( mp ) )
  2939.             {
  2940.                 switch( msg->Command )
  2941.                 {
  2942.                     case COMMAND_NEXT_BUFFER:
  2943.                         if( releaseAudio )
  2944.                         {
  2945.                             ObtainSemaphoreShared( &id->Lock );
  2946.                             sample = id->Sample;
  2947.                             length = id->SampleLength;
  2948.                             samples = ( length > buffersize ) ? buffersize : length;
  2949.                             rcv = audiompmsk;
  2950.                             ReleaseSemaphore( &id->Lock );
  2951.                         }
  2952.                     break;
  2953.                     
  2954.                     case COMMAND_INIT:
  2955.                         dbug( kprintf( "child/COMMAND_INIT\n"); )
  2956.                     
  2957.                         id = (struct InstanceData *) msg->Data;
  2958.                         cb = id->ClassBase;
  2959.                     
  2960.                         if( ! ( msg->Data = mp = CreateMsgPort() ) )
  2961.                         {
  2962.                             ReplyMsg( &msg->Message );
  2963.                             return;
  2964.                         }
  2965.  
  2966.                         mpmsk = 1L << mp->mp_SigBit;
  2967.                     break;
  2968.                     
  2969.                     case COMMAND_EXIT:
  2970.                     case COMMAND_STOP:
  2971.                         dbug( kprintf( "child/COMMAND_EXIT or STOP\n"); )
  2972.                     
  2973.                         if( releaseAudio )
  2974.                         {
  2975.                             LONG    i;
  2976.                             
  2977.                             SetTDMode( cb, id, BUT_STOP );
  2978.                             
  2979.                             for( i = AUDIO_LEFT; i < NUM_REQUESTS; i++ )
  2980.                             {
  2981.                                 struct IORequest    *ioa = (struct IORequest *) ioaudio[ i ];
  2982.                                 
  2983.                                 if( CheckIO( ioa ) )
  2984.                                 {
  2985.                                     RemoveRequest( ioa );
  2986.                                 }
  2987.                                 else
  2988.                                 {
  2989.                                     AbortIO( ioa );
  2990.                                     WaitIO( ioa );
  2991.                                 }
  2992.                             }
  2993.                             
  2994.                             CloseDevice( (struct IORequest *) ioaudio[ AUDIO_CONTROL ] );
  2995.                             DeleteMsgPort( mpaudio );
  2996.                             audiompmsk = 0L;
  2997.                             FreeVec( ioaudio[ AUDIO_CONTROL ] );
  2998.                             FreeVec( buffer[0] ); buffer[0] = NULL;
  2999.                             releaseAudio = FALSE;                            
  3000.                         }
  3001.                         
  3002.                         if( msg->Command == COMMAND_EXIT )
  3003.                         {
  3004.                             Forbid();
  3005.                             ReplyMsg( &msg->Message );
  3006.                             DeleteMsgPort( mp );
  3007.                             return;
  3008.                         }
  3009.                     break;
  3010.                     
  3011.                     case COMMAND_PERVOL:
  3012.                     {
  3013.                         dbug( kprintf( "child/COMMAND_PERVOL\n"); )
  3014.                         
  3015.                         if( releaseAudio )
  3016.                         {
  3017.                             struct IOAudio *ioa = ioaudio[ AUDIO_CONTROL ];
  3018.                             
  3019.                             ObtainSemaphoreShared( &id->Lock );
  3020.                             
  3021.                             if( numChAllocated == 1L || IsStereo( id->SampleType ) )
  3022.                             {
  3023.                                 ioa->ioa_Period    = Freq2Period( id->Frequency );
  3024.                                 ioa->ioa_Volume    = id->Volume;
  3025.                                 ioa->ioa_Request.io_Flags     = 0;
  3026.                                 ioa->ioa_Request.io_Command = ADCMD_PERVOL;
  3027.                                 DoIO( &ioa->ioa_Request );
  3028.                                 
  3029.                                 Forbid();
  3030.                                 ioaudio[ AUDIO_LEFT ]->ioa_Volume =
  3031.                                 ioaudio[ AUDIO_LEFT2 ]->ioa_Volume = 
  3032.                                 ioaudio[ AUDIO_RIGHT ]->ioa_Volume =
  3033.                                 ioaudio[ AUDIO_RIGHT2 ]->ioa_Volume = id->Volume;
  3034.                                 Permit();
  3035.                             }
  3036.                             else
  3037.                             {
  3038.                                 UWORD    leftvol, rightvol;
  3039.                                 ULONG    oldmask = (ULONG) ioa->ioa_Request.io_Unit;
  3040.                                 
  3041.                                 CalcPanVol( id->Volume, id->Panning, &leftvol, &rightvol );
  3042.                                 /*
  3043.                                 ioa->ioa_Request.io_Command = CMD_STOP;
  3044.                                 DoIO( &ioa->ioa_Request );*/
  3045.                                 
  3046.                                 ioa->ioa_Request.io_Unit = (struct Unit *) ( oldmask & LEFT_MASK );
  3047.                                 ioa->ioa_Period    = Freq2Period( id->Frequency );
  3048.                                 ioa->ioa_Volume    = leftvol;
  3049.                                 ioa->ioa_Request.io_Flags     = 0;
  3050.                                 ioa->ioa_Request.io_Command = ADCMD_PERVOL;
  3051.                                 DoIO( &ioa->ioa_Request );
  3052.                                 
  3053.                                 ioa->ioa_Request.io_Unit = (struct Unit *) ( oldmask & RIGHT_MASK );
  3054.                                 ioa->ioa_Period    = Freq2Period( id->Frequency );
  3055.                                 ioa->ioa_Volume    = rightvol;
  3056.                                 ioa->ioa_Request.io_Flags     = 0;
  3057.                                 ioa->ioa_Request.io_Command = ADCMD_PERVOL;
  3058.                                 DoIO( &ioa->ioa_Request );
  3059.                                 
  3060.                                 ioa->ioa_Request.io_Unit = (struct Unit *) oldmask;
  3061.                                 
  3062.                                 Forbid();
  3063.                                 ioaudio[ AUDIO_LEFT ]->ioa_Volume =
  3064.                                 ioaudio[ AUDIO_LEFT2 ]->ioa_Volume = leftvol;
  3065.                                 ioaudio[ AUDIO_RIGHT ]->ioa_Volume =
  3066.                                 ioaudio[ AUDIO_RIGHT2 ]->ioa_Volume = rightvol;
  3067.                                 Permit();
  3068.  
  3069.                                 /*
  3070.                                 ioa->ioa_Request.io_Command = CMD_START;
  3071.                                 DoIO( &ioa->ioa_Request );*/
  3072.                             }
  3073.                             
  3074.                             Forbid();
  3075.                             ioaudio[ AUDIO_LEFT ]->ioa_Period =
  3076.                             ioaudio[ AUDIO_LEFT2 ]->ioa_Period =
  3077.                             ioaudio[ AUDIO_RIGHT ]->ioa_Period =
  3078.                             ioaudio[ AUDIO_RIGHT2 ]->ioa_Period = Freq2Period( id->Frequency );
  3079.                             Permit();
  3080.                             
  3081.                             ReleaseSemaphore( &id->Lock );
  3082.                         }
  3083.                     }
  3084.                     break;
  3085.                     
  3086.                     case COMMAND_PAUSE:
  3087.                     {
  3088.                         dbug( kprintf( "child/COMMAND_PAUSE\n"); )
  3089.                         
  3090.                         if( releaseAudio )
  3091.                         {
  3092.                             if( ! paused )
  3093.                             {
  3094.                                 ioaudio[ AUDIO_CONTROL ]->ioa_Request.io_Command = CMD_STOP;
  3095.                                 DoIO( &ioaudio[ AUDIO_CONTROL ]->ioa_Request );
  3096.                                 paused = TRUE;
  3097.                             }
  3098.                         }
  3099.                     }
  3100.                     break;
  3101.                     
  3102.                     case COMMAND_PLAY:
  3103.                     {
  3104.                         dbug( kprintf( "child/COMMAND_PLAY\n"); )
  3105.  
  3106.                         ObtainSemaphoreShared( &id->Lock );
  3107.                         
  3108.                         if( releaseAudio )
  3109.                         {
  3110.                             if( paused )                            
  3111.                             {    
  3112.                                 rcv = audiompmsk;
  3113.                                 restart = TRUE;
  3114.                                 paused = FALSE;
  3115.                             }
  3116.                             else
  3117.                             {
  3118.                                 LONG    i;
  3119.                                 
  3120.                                 for( i = AUDIO_LEFT; i < NUM_REQUESTS; i++ )
  3121.                                 {
  3122.                                     struct IORequest    *ioa = &ioaudio[ i ]->ioa_Request;
  3123.                                     
  3124.                                     if( CheckIO( ioa ) )
  3125.                                     {
  3126.                                         RemoveRequest( ioa );
  3127.                                     }
  3128.                                     else
  3129.                                     {
  3130.                                         AbortIO( ioa );
  3131.                                         WaitIO( ioa );
  3132.                                     }
  3133.                                 }
  3134.                                 
  3135.                                 sample = id->Sample;
  3136.                                 length = id->SampleLength;
  3137.                                 samples = buffersize;
  3138.                                 if( length <= buffersize )
  3139.                                 {
  3140.                                     loops = 1L;
  3141.                                     cycles = id->Cycles;
  3142.                                 }
  3143.                                 else
  3144.                                 {
  3145.                                     loops = id->Cycles;
  3146.                                     cycles = 1L;
  3147.                                 }
  3148.                             }
  3149.                         }                        
  3150.                         else                                            
  3151.                         {
  3152.                             UBYTE    ChMap[] = {
  3153.                                 LEFT_CHANNEL_0 | RIGHT_CHANNEL_1,
  3154.                                 LEFT_CHANNEL_3 | RIGHT_CHANNEL_2,
  3155.                                 LEFT_CHANNEL_0, LEFT_CHANNEL_3,
  3156.                                 RIGHT_CHANNEL_1, RIGHT_CHANNEL_2
  3157.                             };
  3158.                             struct IOAudio    *ioa;
  3159.                             LONG            i;
  3160.                             
  3161.                             if( ! id->Sample || ! id->SampleLength )
  3162.                             {
  3163.                                 break;
  3164.                             }
  3165.                             
  3166.                             dbug( kprintf( "child/allocating requests\n" ); )
  3167.                             
  3168.                             /*- allocate requests and msgport -*/
  3169.                             if(    ! ( ioa = AllocVec( sizeof( *ioa ) * NUM_REQUESTS, MEMF_PUBLIC|MEMF_CLEAR ) ) || 
  3170.                                 ! ( mpaudio = CreateMsgPort() ) )
  3171.                             {
  3172.                                 FreeVec( ioa );
  3173.                                 SetTDMode( cb, id, BUT_STOP );
  3174.                                 break;
  3175.                             }
  3176.                             
  3177.                             for( i = 0; i < NUM_REQUESTS; i++ )
  3178.                             {
  3179.                                 ioaudio[i] = ioa++;
  3180.                             }
  3181.                             
  3182.                             audiompmsk = 1L << mpaudio->mp_SigBit;
  3183.                             
  3184.                             /*- Open audio.device and intialize requests -*/
  3185.                             ioa = ioaudio[ AUDIO_CONTROL ];
  3186.                             ioa->ioa_Request.io_Message.mn_ReplyPort = mpaudio;
  3187.                             ioa->ioa_Request.io_Message.mn_Length = sizeof( *ioa );
  3188.                             ioa->ioa_Data = ChMap;
  3189.                             ioa->ioa_Length = sizeof( ChMap );
  3190.                             
  3191.                             if( ! OpenDevice( "audio.device", 0L, (struct IORequest *) ioa, 0L ) )
  3192.                             {
  3193.                                 /*- make CheckIO() work -*/
  3194.                                 ioa->ioa_Request.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  3195.                                 
  3196.                                 for( i = 1; i < NUM_REQUESTS; i++ )
  3197.                                 {
  3198.                                     CopyMem( ioa, ioaudio[i], sizeof( *ioa ) );
  3199.                                 }
  3200.                                 
  3201.                                 for( i = 0; i < sizeof( ChMap ); i++ )
  3202.                                 {
  3203.                                     if( (ULONG) ioa->ioa_Request.io_Unit == (ULONG) ChMap[i] )
  3204.                                     {
  3205.                                         break;
  3206.                                     }
  3207.                                 }
  3208.                                 
  3209.                                 if( i < 2 )
  3210.                                 {
  3211.                                     dbug( kprintf( "child/got two stereo channels\n" ); )
  3212.                                     numChAllocated = 2L;                            
  3213.                                     /*- stop device in order to sync stereo channels -*/
  3214.                                     ioa->ioa_Request.io_Command = CMD_STOP;
  3215.                                     DoIO( &ioa->ioa_Request );
  3216.                                     restart = TRUE;
  3217.                                 }
  3218.                                 else
  3219.                                 {
  3220.                                     dbug( kprintf( "child/got only one channel\n" ); )
  3221.                                     numChAllocated = 1L;
  3222.                                     restart = FALSE;
  3223.                                 }
  3224.                                 
  3225.                                 ioaudio[ AUDIO_LEFT   ]->ioa_Request.io_Unit =
  3226.                                 ioaudio[ AUDIO_LEFT2 ]->ioa_Request.io_Unit = (struct Unit *) ( (ULONG) ioa->ioa_Request.io_Unit & LEFT_MASK );
  3227.                                 ioaudio[ AUDIO_RIGHT   ]->ioa_Request.io_Unit =
  3228.                                 ioaudio[ AUDIO_RIGHT2 ]->ioa_Request.io_Unit = (struct Unit *) ( (ULONG) ioa->ioa_Request.io_Unit & RIGHT_MASK );
  3229.                                 
  3230.                                 sample = id->Sample;
  3231.                                 length = id->SampleLength;
  3232.                     
  3233.                                 if( ( id->SampleType == SDTST_M8S ) && ( TypeOfMem( sample ) & MEMF_CHIP ) )
  3234.                                 {
  3235.                                     buffersize = samples = ( length > MAX_SAMPLE ) ? MAX_SAMPLE : length;
  3236.                                     dbug( kprintf( "child/chip sample\n" ); )
  3237.                                 }
  3238.                                 /*- allocate buffers -*/
  3239.                                 else
  3240.                                 {    
  3241.                                     ObtainSemaphoreShared( &cb->cb_LibLock ); /* determine buffersize, don't go below 1k (heavy system load) */
  3242.                                     buffersize =  ( length > cb->cb_BufferSize ) ? cb->cb_BufferSize : ( ((length+1)/2) < 1024L ? length : (length+1)/2 );
  3243.                                     ReleaseSemaphore( &cb->cb_LibLock );
  3244.                                     
  3245.                                     while( ! ( buffer[0] = AllocVec( buffersize << numChAllocated, MEMF_CHIP ) ) )
  3246.                                     {
  3247.                                         dbug( kprintf( "child/failed to allocate %ld bytes of buffer\n", buffersize ); )
  3248.                                         if( (buffersize /= 2) < 1024L )
  3249.                                         {
  3250.                                             break;
  3251.                                         }
  3252.                                     }
  3253.                                     
  3254.                                     samples = buffersize;
  3255.                                     
  3256.                                     dbug( kprintf( "child/Buffer at %08lx, size %ld, num %ld\n", buffer[0], buffersize, numChAllocated*2 ); )
  3257.                                     
  3258.                                     if( buffer[0] == NULL )
  3259.                                     {
  3260.                                         CloseDevice( (struct IORequest *) ioa );
  3261.                                         DeleteMsgPort( mpaudio );
  3262.                                         audiompmsk = 0L;
  3263.                                         FreeVec( ioa );
  3264.                                         SetTDMode( cb, id, BUT_STOP );
  3265.                                         break;
  3266.                                     }
  3267.                                     
  3268.                                     for( i = 1; i < 4; i++ )
  3269.                                     {                            
  3270.                                         buffer[ i ] = buffer[ i-1 ] + buffersize;
  3271.                                     }
  3272.                                 }
  3273.                                 
  3274.                                 if( buffersize <= length )
  3275.                                 {
  3276.                                     cycles = id->Cycles;
  3277.                                     loops = 1L;
  3278.                                 }
  3279.                                 else
  3280.                                 {
  3281.                                     cycles = 1L;
  3282.                                     loops = id->Cycles;
  3283.                                 }
  3284.                                 
  3285.                                 dbug( kprintf( "child/Sample: %08lx, Length: %ld, Cycles: %ld, Loops: %ld, Freq: %ld\n", sample, length, cycles, loops, id->Frequency ); )
  3286.                                 
  3287.                                 releaseAudio = TRUE;
  3288.                                 rcv = audiompmsk;
  3289.                                 SetTDMode( cb, id, BUT_PLAY );
  3290.                             }
  3291.                             else
  3292.                             {
  3293.                                 dbug( kprintf("child/can't open audio.device\n"); )
  3294.                                 DeleteMsgPort( mpaudio );
  3295.                                 audiompmsk = 0L;
  3296.                                 FreeVec( ioa );
  3297.                                 SetTDMode( cb, id, BUT_STOP );
  3298.                             }
  3299.                         }
  3300.                     
  3301.                         ReleaseSemaphore( &id->Lock );
  3302.                     }
  3303.                     break;
  3304.                 } // switch
  3305.             
  3306.                 if( msg->Message.mn_ReplyPort )
  3307.                 {
  3308.                     ReplyMsg( &msg->Message );
  3309.                 }
  3310.                 else // NT_FREEMSG
  3311.                 {
  3312.                     FreeVec( msg );
  3313.                 }
  3314.             } // while
  3315.         } // if
  3316.         
  3317.         if( rcv & audiompmsk )
  3318.         {
  3319.             ObtainSemaphoreShared( &id->Lock );
  3320.             
  3321.             if( length == 0L )
  3322.             {
  3323.                 LONG    i;
  3324.                 BOOL    Done = TRUE;
  3325.                     
  3326.                 dbug( kprintf( "child/reachend end of sample\n" ); )
  3327.                 
  3328.                 /*- wait for any outstanding request -*/
  3329.                 for( i = AUDIO_LEFT; i < NUM_REQUESTS; i++ )
  3330.                 {
  3331.                     struct IORequest    *ioa = &ioaudio[i]->ioa_Request;
  3332.                         
  3333.                     if( ! CheckIO( ioa ) )
  3334.                     {
  3335.                         /* don't block doing WaitIO() */
  3336.                         Done = FALSE;
  3337.                     }
  3338.                     else
  3339.                     {
  3340.                         RemoveRequest( ioa );
  3341.                     }
  3342.                 }
  3343.                 
  3344.                 if( ! Done || id->Continuous )
  3345.                 {
  3346.                     ReleaseSemaphore( &id->Lock );
  3347.                     continue;
  3348.                 }
  3349.                 
  3350.                 if(  id->Repeat || ( --loops > 0L ) )
  3351.                 {
  3352.                     dbug( kprintf( "child/%ld loops to go\n", loops ); )
  3353.                                 
  3354.                     sample = id->Sample;
  3355.                     length = id->SampleLength;
  3356.                     samples = buffersize;
  3357.                     /*- stop device in order to sync stereo channels -*/
  3358.                     if( numChAllocated == 2L )
  3359.                     {
  3360.                         ioaudio[ AUDIO_CONTROL ]->ioa_Request.io_Command = CMD_STOP;
  3361.                         DoIO( &ioaudio[ AUDIO_CONTROL ]->ioa_Request );
  3362.                         restart = TRUE;
  3363.                     }
  3364.                     else
  3365.                     {
  3366.                         restart = FALSE;
  3367.                     }
  3368.                 }
  3369.                 else
  3370.                 {
  3371.                     dbug( kprintf("child/cleanup\n"); )
  3372.                     
  3373.                     /*- cleanup -*/
  3374.                     CloseDevice( &ioaudio[AUDIO_CONTROL]->ioa_Request );
  3375.                     FreeVec( buffer[0] ); buffer[0] = NULL;
  3376.                     FreeVec( ioaudio[ AUDIO_CONTROL ] );
  3377.                     DeleteMsgPort( mpaudio ); audiompmsk = 0L;
  3378.                     releaseAudio = FALSE;
  3379.                     
  3380.                     SetTDMode( cb, id, BUT_STOP );
  3381.                     
  3382.                     if( id->SignalTask && id->SignalBit != -1L )
  3383.                     {
  3384.                         Signal( id->SignalTask, 1L << id->SignalBit );
  3385.                     }
  3386.                 }
  3387.             }
  3388.             
  3389.             if( length )
  3390.             {            
  3391.                 LONG    i;
  3392.                 UWORD    volleft, volright;
  3393.                 
  3394.                 if( numChAllocated == 1L || IsStereo( id->SampleType ) )
  3395.                 {
  3396.                     volright =
  3397.                     volleft = id->Volume;
  3398.                 }
  3399.                 else
  3400.                 {
  3401.                     CalcPanVol( id->Volume, id->Panning, &volleft, &volright );
  3402.                 }
  3403.                 
  3404.                 /*- we work doublebuffered -*/
  3405.                 for( i = 0; i < 2; i++ )
  3406.                 {
  3407.                     struct IOAudio    *ioa_left = ioaudio[ i + AUDIO_LEFT ],
  3408.                                     *ioa_right = ioaudio[ i + AUDIO_RIGHT ];
  3409.                     
  3410.                     /*- get free audiorequest -*/
  3411.                     if( CheckIO( (struct IORequest *) ioa_left ) && CheckIO( (struct IORequest *) ioa_right ) )
  3412.                     {    
  3413.                         BYTE    *data_left, *data_right;
  3414.                         
  3415.                         dbug( kprintf( "child/Request pair #%ld is free\n", i ); )
  3416.                         
  3417.                         RemoveRequest( (struct IORequest *) ioa_left );
  3418.                         RemoveRequest( (struct IORequest *) ioa_right );
  3419.                         
  3420.                         if( buffer[ 0 ] )
  3421.                         {
  3422.                             if( IsStereo( id->SampleType ) )
  3423.                             {
  3424.                                 LONG    c, add = ( id->SampleType == SDTST_S16S ) ? 2 : 1;
  3425.                                     
  3426.                                 if( numChAllocated == 2L )
  3427.                                 {
  3428.                                     BYTE    *buf_left = buffer[ i * 2 ],
  3429.                                             *buf_right = buffer[ i * 2 + 1 ];
  3430.  
  3431.                                     data_left = buf_left;
  3432.                                     data_right = buf_right;
  3433.                                 
  3434.                                     for( c = samples; c; c-- )
  3435.                                     {
  3436.                                         *buf_left++ = *sample; sample += add;
  3437.                                         *buf_right++ = *sample; sample += add;
  3438.                                     }
  3439.                                 }
  3440.                                 else
  3441.                                 {
  3442.                                     BYTE    *buf = buffer[ i ];
  3443.  
  3444.                                     data_left = 
  3445.                                     data_right = buf;
  3446.                                 
  3447.                                     for( c = samples; c; c--, sample+=(add<<1) )
  3448.                                     {
  3449.                                         *buf++ = ( sample[0] + sample[add] ) >> 1;
  3450.                                     }
  3451.                                 }
  3452.                             }
  3453.                             else
  3454.                             {
  3455.                                 BYTE    *buf = buffer[ i ];
  3456.  
  3457.                                 data_left = 
  3458.                                 data_right = buf;
  3459.                                 
  3460.                                 if( id->SampleType == SDTST_M8S )
  3461.                                 {
  3462.                                     if( (ULONG) sample&3 || (ULONG) buf&3 || samples&3 )
  3463.                                     {
  3464.                                         CopyMem( sample, buf, samples );
  3465.                                     }
  3466.                                     else
  3467.                                     {
  3468.                                         CopyMemQuick( sample, buf, samples );
  3469.                                     }
  3470.                                     
  3471.                                     sample += samples;
  3472.                                 }
  3473.                                 else
  3474.                                 {
  3475.                                     LONG    c;
  3476.                                     
  3477.                                     for( c = samples; c; c--, sample+=2 )
  3478.                                     {
  3479.                                         *buf++ = *sample;
  3480.                                     }
  3481.                                 }
  3482.                             }
  3483.                         }
  3484.                         else
  3485.                         {
  3486.                             data_left =
  3487.                             data_right = sample;
  3488.                             sample += samples;
  3489.                         }
  3490.                         
  3491.                         ioa_left->ioa_Data = data_left;
  3492.                         ioa_left->ioa_Length = samples;
  3493.                         ioa_left->ioa_Cycles = cycles;
  3494.                         ioa_left->ioa_Period = Freq2Period( id->Frequency );
  3495.                         ioa_left->ioa_Volume = volleft;
  3496.                         ioa_left->ioa_Request.io_Flags = ADIOF_PERVOL;
  3497.                         ioa_left->ioa_Request.io_Command = CMD_WRITE;
  3498.                         BeginIO( (struct IORequest *) ioa_left );
  3499.                         
  3500.                         if( numChAllocated == 2L )
  3501.                         {
  3502.                             ioa_right->ioa_Data = data_right;
  3503.                             ioa_right->ioa_Length = samples;
  3504.                             ioa_right->ioa_Cycles = cycles;
  3505.                             ioa_right->ioa_Period = Freq2Period( id->Frequency );
  3506.                             ioa_right->ioa_Volume = volright;
  3507.                             ioa_right->ioa_Request.io_Flags = ADIOF_PERVOL;
  3508.                             ioa_right->ioa_Request.io_Command = CMD_WRITE;
  3509.                             BeginIO( (struct IORequest *) ioa_right );
  3510.                         }
  3511.                         
  3512.                         if( (length-=samples) < samples )
  3513.                         {
  3514.                             samples = length;
  3515.                         } // if
  3516.                     } // if
  3517.                     else
  3518.                     {
  3519.                         dbug( kprintf( "child/Req #%ld in use\n", i ); )
  3520.                     }
  3521.                 
  3522.                     if( ! length )
  3523.                     {
  3524.                         /* a continuous stream of data? */
  3525.                         if( id->Continuous )
  3526.                         {
  3527.                             /* notify */
  3528.                             if( id->SignalTask && id->SignalBit != -1L )
  3529.                             {
  3530.                                 Signal( id->SignalTask, 1L << id->SignalBit );
  3531.                             }
  3532.                         }
  3533.                         
  3534.                         break;
  3535.                     }
  3536.                 } // for
  3537.                 
  3538.                 if( restart )
  3539.                 {
  3540.                     dbug( kprintf( "child/starting stereo channels\n" ); )
  3541.                     ioaudio[ AUDIO_CONTROL ]->ioa_Request.io_Command = CMD_START;
  3542.                     DoIO( &ioaudio[ AUDIO_CONTROL ]->ioa_Request );
  3543.                     restart = FALSE;
  3544.                 } // if
  3545.             } // if
  3546.         
  3547.             ReleaseSemaphore( &id->Lock );
  3548.         } // if
  3549.     } // while
  3550.     
  3551. #ifndef __MAXON__
  3552. #define SysBase    cb->cb_SysBase
  3553. #endif
  3554. }
  3555.  
  3556. /****************************************************************************/
  3557.  
  3558. void __regargs CloseAHI( struct MsgPort *mp, struct AHIRequest *ahir )
  3559. {
  3560. #ifndef __MAXON__
  3561. #undef SysBase
  3562.     struct Library    *SysBase = (*(struct Library **)4L);
  3563. #endif    
  3564.     CloseDevice( (struct IORequest *) ahir );
  3565.     DeleteIORequest( (struct IORequest *) ahir );
  3566.     DeleteMsgPort( mp );
  3567. #ifndef __MAXON__
  3568. #define SysBase    cb->cb_SysBase
  3569. #endif
  3570. }
  3571.  
  3572. /****************************************************************************/
  3573.  
  3574. struct Library * __regargs OpenAHI( struct MsgPort **mpp, struct AHIRequest **iop )
  3575. {
  3576. #ifndef __MAXON__
  3577. #undef SysBase
  3578.     struct Library    *SysBase = (*(struct Library **)4L);
  3579. #endif
  3580.     struct MsgPort    *mp;
  3581.     struct AHIRequest    *ahir;
  3582.     
  3583.     mp = CreateMsgPort();
  3584.     if( ahir = (struct AHIRequest *) CreateIORequest( mp, sizeof( struct AHIRequest ) ) )
  3585.     {
  3586.         ahir->ahir_Version = 4;
  3587.         if( ! OpenDevice( "ahi.device", AHI_NO_UNIT, (struct IORequest *)ahir, 0L ) )
  3588.         {
  3589.             *mpp = mp;
  3590.             *iop = ahir;
  3591.             return( (struct Library *) ahir->ahir_Std.io_Device );
  3592.         }
  3593.         else
  3594.         {
  3595.             dbug( kprintf( "Can't open ahi.device v4\n" ); )
  3596.         }
  3597.         
  3598.         DeleteIORequest( (struct IORequest *) ahir );
  3599.     }
  3600.     else
  3601.     {
  3602.         dbug( kprintf( "no memory for ahirequest or msgport\n" ); )
  3603.     }
  3604.     DeleteMsgPort( mp );
  3605.     
  3606.     return FALSE;
  3607. #ifndef __MAXON__
  3608. #define SysBase    cb->cb_SysBase
  3609. #endif
  3610. }
  3611.  
  3612. /****************************************************************************/
  3613.  
  3614.  
  3615. struct SoundFuncData {
  3616.     UWORD        CyclesLeft;
  3617.     UWORD        Cycles;
  3618.     UWORD        Channels;
  3619.     UWORD        Sound;
  3620.     BOOL        Continuous;
  3621.     BOOL        Valid[2];
  3622.     BOOL        Restart;
  3623.     BOOL        *Repeat;
  3624.     struct Task    *SigTask;
  3625. #ifndef __MAXON__
  3626. #undef SysBase
  3627.     struct Library    *AHIBase;
  3628.     struct Library    *SysBase;
  3629. #define AHIBase    sfd->AHIBase
  3630. #define SysBase    sfd->SysBase
  3631. #endif
  3632. };
  3633.  
  3634. #ifdef __MAXON__
  3635. void SoundFunc( struct Hook *h, struct AHIAudioCtrl *actrl, struct AHISoundMessage *ahism )
  3636. #else
  3637. void __interrupt SoundFunc( REG(a0, struct Hook *h),  REG(a2, struct AHIAudioCtrl *actrl), REG(a1, struct AHISoundMessage *ahism) )
  3638. #endif
  3639. {
  3640.     struct SoundFuncData    *sfd = (struct SoundFuncData *) h->h_Data;
  3641.     
  3642.     dbug( kprintf( "SoundFunc\n" ); )
  3643.     
  3644.     if( ! ( *sfd->Repeat ) )
  3645.     {
  3646.         if( ! ( sfd->CyclesLeft-- ) )
  3647.         {
  3648.             LONG    i, snd = sfd->Sound;
  3649.         
  3650.             sfd->Valid[ snd ] = FALSE;
  3651.         
  3652.             sfd->Sound = snd = ( sfd->Continuous ) ? ! snd : AHI_NOSOUND;
  3653.             /* no echos please */
  3654.             if( ! sfd->Valid[ snd ] )
  3655.             {
  3656.                 snd = AHI_NOSOUND;
  3657.                 sfd->Restart = TRUE;
  3658.             }
  3659.     
  3660.             for( i = 0; i < sfd->Channels; i++ )
  3661.             {
  3662.                 AHI_SetSound( i, snd, 0L, 0L, actrl, 0L );
  3663.             }
  3664.             
  3665.             sfd->CyclesLeft = sfd->Cycles;
  3666.             
  3667.             Signal ( sfd->SigTask, SIGBREAKF_CTRL_C );
  3668.         }
  3669.     }
  3670. }
  3671.  
  3672. #ifndef __MAXON__
  3673. #undef AHIBase
  3674. #undef SysBase
  3675. #define SysBase    cb->cb_SysBase
  3676. #endif
  3677.  
  3678. /****************************************************************************/
  3679.  
  3680. void PlayerProcAHI( void )
  3681. {
  3682. #ifndef __MAXON__
  3683. #undef SysBase
  3684.     struct Library            *SysBase = (*(struct Library **)4L);
  3685.     struct Library            *AHIBase = NULL;
  3686. #endif
  3687.     struct Process        *pr = (struct Process *) FindTask( NULL );
  3688.     struct MsgPort        *mp, *AHImp;
  3689.     struct AHIRequest        *ahir;
  3690.     struct AHIAudioCtrl     *actrl;
  3691.     struct SoundFuncData    *sfd;
  3692.     struct Hook            *SoundHook = NULL;
  3693.     struct ClassBase        *cb;
  3694.     struct InstanceData    *id;
  3695.     ULONG                mpmsk, numCh, buffersize;
  3696.     BOOL                stereo, paused = FALSE, failed;
  3697.     static UBYTE            sdtst2ahist[] = { AHIST_M8S, AHIST_S8S, AHIST_M16S, AHIST_S16S };
  3698.     BYTE                *buffer = NULL;
  3699.     
  3700.     mp = &pr->pr_MsgPort;
  3701.     mpmsk = 1L << mp->mp_SigBit;
  3702.     
  3703.     dbug( kprintf( "child launched\n" ); )
  3704.     
  3705.     for( ;; )
  3706.     {
  3707.         LONG            rcv;
  3708.         struct ObjectMsg    *msg;
  3709.         
  3710.         rcv = Wait( mpmsk | SIGBREAKF_CTRL_C );
  3711.         
  3712.         if( rcv & mpmsk )
  3713.         {
  3714.             while( msg = (struct ObjectMsg *) GetMsg( mp ) )
  3715.             {
  3716.                 switch( msg->Command )
  3717.                 {
  3718.                     case COMMAND_NEXT_BUFFER:
  3719.                     {
  3720.                         dbug( kprintf( "child: COMMAND_NEXT_BUFFER\n"); )
  3721.  
  3722.                         ObtainSemaphoreShared( &id->Lock );
  3723.  
  3724.                         if( AHIBase )
  3725.                         {
  3726.                             BYTE    *dst = ( sfd->Sound ) ? &buffer[ buffersize ] : buffer;
  3727.                             ULONG    transfer = UMult( id->SampleLength, bytesPerPoint[ id->SampleType ] ), i;
  3728.                             
  3729.                             if( transfer > buffersize )
  3730.                             {
  3731.                                 transfer = buffersize;
  3732.                             }
  3733.                             
  3734.                             if( (ULONG)id->Sample&3 || (ULONG)dst&3 || transfer&3 )
  3735.                             {
  3736.                                 CopyMem( id->Sample, dst, transfer );
  3737.                             }
  3738.                             else
  3739.                             {
  3740.                                 CopyMemQuick( id->Sample, dst, transfer );
  3741.                             }
  3742.                             
  3743.                             for( i = transfer; i < buffersize; i++ )
  3744.                             {
  3745.                                 dst[ i ] = 0;
  3746.                             }
  3747.                             
  3748.                             sfd->Valid[ sfd->Sound ] = TRUE;
  3749.                             
  3750.                             /* new sample wasn't available fast enough */
  3751.                             if( sfd->Restart )
  3752.                             {
  3753.                                 sfd->Restart = FALSE;
  3754.                                 
  3755.                                 dbug( kprintf( "restart playback\n" ); )
  3756.                                 
  3757.                                 for( i = 0; i < numCh; i++ )
  3758.                                 {
  3759.                                     AHI_SetSound( i, sfd->Sound, 0,0, actrl, AHISF_IMM );
  3760.                                 }
  3761.                             }
  3762.                         }
  3763.                     
  3764.                         ReleaseSemaphore( &id->Lock );
  3765.                     }
  3766.                     break;
  3767.                     
  3768.                     case COMMAND_INIT:
  3769.                         dbug( kprintf("child: COMMAND_INIT\n"); )
  3770.                     
  3771.                         id = (struct InstanceData *) msg->Data;
  3772.                         cb = id->ClassBase;
  3773.                     
  3774.                         if( ! ( mp = msg->Data = CreateMsgPort() ) )
  3775.                         {
  3776.                             ReplyMsg( &msg->Message );
  3777.                             return;
  3778.                         }
  3779.                     
  3780.                         mpmsk = 1L << mp->mp_SigBit;
  3781.                     break;
  3782.                     
  3783.                     case COMMAND_EXIT:
  3784.                     case COMMAND_STOP:
  3785.                     {
  3786.                         dbug( kprintf("child: COMMAND_STOP/EXIT\n"); )
  3787.                         
  3788.                         if( AHIBase )
  3789.                         {
  3790.                             AHI_FreeAudio( actrl );
  3791.                             FreeVec( SoundHook );
  3792.                             FreeVec( buffer );
  3793.                             buffer = NULL;
  3794.                             CloseAHI( AHImp, ahir );
  3795.                             AHIBase = NULL;
  3796.                             
  3797.                             SetTDMode( cb, id, BUT_STOP );
  3798.                         }
  3799.                             
  3800.                         if( msg->Command == COMMAND_EXIT )
  3801.                         {
  3802.                             Forbid();
  3803.                             ReplyMsg( &msg->Message );
  3804.                             DeleteMsgPort( mp );
  3805.                             return;
  3806.                         }
  3807.                     }
  3808.                     break;
  3809.                     
  3810.                     case COMMAND_PERVOL:
  3811.                         dbug( kprintf("child: COMMAND_PERVOL\n"); )
  3812.                     
  3813.                         if( AHIBase )
  3814.                         {
  3815.                             ULONG            freq, vol, pan, i;
  3816.                             
  3817.                             ObtainSemaphoreShared( &id->Lock );
  3818.                             pan = id->Panning;
  3819.                             vol = ( id->Volume << 16 ) >> 6;
  3820.                             freq = id->Frequency;
  3821.                             ReleaseSemaphore( &id->Lock );
  3822.                             
  3823.                             for( i = 0; i < numCh; i++ )
  3824.                             {
  3825.                                 if( ! paused ) 
  3826.                                 {
  3827.                                     AHI_SetFreq( i, freq, actrl, AHISF_IMM );
  3828.                                 }
  3829.                                 AHI_SetVol( i, vol, pan, actrl, AHISF_IMM );
  3830.                             }
  3831.                         }
  3832.                     break;
  3833.                     
  3834.                     case COMMAND_PAUSE:
  3835.                     {
  3836.                         if( AHIBase )
  3837.                         {
  3838.                             if( ! paused )
  3839.                             {
  3840.                                 LONG    i;
  3841.                                 
  3842.                                 for( i = 0; i < numCh; i++ )
  3843.                                 {
  3844.                                     AHI_SetFreq( i, 0L, actrl, AHISF_IMM );
  3845.                                 }
  3846.                              
  3847.                                 paused = TRUE;
  3848.                             }
  3849.                         }
  3850.                     }
  3851.                     break;
  3852.                     
  3853.                     case COMMAND_PLAY:
  3854.                         dbug( kprintf("child: COMMAND_PLAY\n"); )
  3855.                     
  3856.                         // ObtainSemaphoreShared( &id->Lock );
  3857.                     
  3858.                         if( AHIBase )
  3859.                         {
  3860.                             if( paused )
  3861.                             {
  3862.                                 LONG    i;
  3863.                                 
  3864.                                 for( i = 0; i < numCh; i++ )
  3865.                                 {
  3866.                                     AHI_SetFreq( i, id->Frequency, actrl, AHISF_IMM );
  3867.                                 }
  3868.                                     
  3869.                                 paused = FALSE;
  3870.                             }
  3871.                             else
  3872.                             {
  3873.                                 LONG    i;
  3874.  
  3875.                                 AHI_ControlAudio( actrl,
  3876.                                     AHIC_Play, FALSE,
  3877.                                     TAG_DONE );
  3878.                                 
  3879.                                 for( i = 0; i < numCh; i++ )
  3880.                                 {
  3881.                                     AHI_SetSound( i, sfd->Sound, 0,0, actrl, AHISF_IMM );
  3882.                                 }
  3883.  
  3884.                                 sfd->CyclesLeft = sfd->Cycles;
  3885.                                 
  3886.                                 AHI_ControlAudio( actrl,
  3887.                                     AHIC_Play, TRUE,
  3888.                                     TAG_DONE );
  3889.                             }
  3890.                         }
  3891.                         else                    
  3892.                         {
  3893.                             failed = TRUE;
  3894.                             
  3895.                             if( AHIBase = OpenAHI( &AHImp, &ahir ) )
  3896.                             {                            
  3897.                                 stereo = IsStereo( id->SampleType );
  3898.                             
  3899.                                 if( SoundHook = (struct Hook *) AllocVec( sizeof( *SoundHook ) + sizeof( *sfd ), MEMF_CLEAR|MEMF_PUBLIC ) )
  3900.                                 {
  3901.                                     ULONG    audioID, mixfreq;
  3902.                                     extern void HookEntry( void );
  3903.                                                                 
  3904.                                     numCh = stereo ? 2 : 1;
  3905.  
  3906.                                     sfd = (struct SoundFuncData *) (SoundHook+1);
  3907. #ifdef __MAXON__                                    
  3908.                                     SoundHook->h_Entry = (HOOKFUNC) HookEntry;
  3909.                                     SoundHook->h_SubEntry = (HOOKFUNC) SoundFunc;
  3910. #else
  3911.                                     SoundHook->h_Entry = (HOOKFUNC) SoundFunc;
  3912. #endif
  3913.                                     SoundHook->h_Data = (APTR) sfd;
  3914.                                     
  3915.                                     sfd->SigTask = &pr->pr_Task;
  3916.                                     sfd->Channels = numCh;
  3917.                                     sfd->Cycles = 
  3918.                                     sfd->CyclesLeft = UMult( id->Cycles, numCh );
  3919. //                                    sfd->Sound = 0;
  3920.                                     sfd->Continuous = id->Continuous;
  3921.                                     sfd->Valid[ 0 ] = TRUE;
  3922.                                     sfd->Repeat = (BOOL *) &id->Repeat;
  3923. //                                    sfd->Valid[ 1 ] = FALSE;
  3924. //                                    sfd->Restart = FALSE;
  3925. #ifndef __MAXON__
  3926.                                     sfd->AHIBase = AHIBase;
  3927.                                     sfd->SysBase = SysBase;
  3928. #endif
  3929.                                     dbug( kprintf("child: ahi is open\n"); )
  3930.                                     
  3931.                                     ObtainSemaphoreShared( &cb->cb_LibLock );
  3932.                                     
  3933.                                     mixfreq = cb->cb_AHIMixFrequency;
  3934.                                     
  3935.                                     if( cb->cb_ForceAHIMode )
  3936.                                     {
  3937.                                         audioID = cb->cb_AHIModeID;
  3938.                                     }
  3939.                                     else
  3940.                                     {
  3941.                                         if( ( audioID = AHI_BestAudioID( 
  3942.                                             ( cb->cb_AHIModeID ? AHIDB_AudioID : TAG_IGNORE ), cb->cb_AHIModeID,
  3943.                                             AHIDB_Volume, TRUE,
  3944.                                             ( ! stereo ? TAG_IGNORE : AHIDB_Stereo ), TRUE,
  3945.                                             ( ! stereo ? AHIDB_Panning : TAG_IGNORE ), TRUE,
  3946.                                             TAG_DONE ) ) == AHI_INVALID_ID )
  3947.                                         {
  3948.                                             audioID = AHI_DEFAULT_ID;
  3949.                                             dbug( kprintf("child: bestaid failed\n"); )
  3950.                                         }
  3951.                                     }
  3952.                                     
  3953.                                     ReleaseSemaphore( &cb->cb_LibLock );
  3954.                                     
  3955.                                     
  3956.                                     if( actrl = AHI_AllocAudio(
  3957.                                         AHIA_AudioID, audioID,
  3958.                                         AHIA_Channels, numCh,
  3959.                                         AHIA_Sounds, ( id->Continuous ) ? 2L : 1L,
  3960.                                         AHIA_MixFreq, mixfreq,
  3961.                                         ( id->Cycles ? AHIA_SoundFunc : TAG_IGNORE), (ULONG) SoundHook,
  3962.                                         TAG_DONE ) )                            
  3963.                                     {
  3964.                                         struct AHISampleInfo    sample;
  3965.                                         ULONG                freq, vol;
  3966.                                         
  3967.                                         freq = id->Frequency;
  3968.                                         vol = ( id->Volume << 16 ) >> 6;
  3969.             
  3970.                                         dbug( kprintf("child: alloc audio okay\n"); )
  3971.                                         
  3972.                                         sample.ahisi_Type = sdtst2ahist[ id->SampleType ];
  3973.                                         sample.ahisi_Length = id->SampleLength;
  3974.                                         
  3975.                                         if( id->Continuous )
  3976.                                         {
  3977.                                             ULONG playsamples;
  3978.                                         
  3979.                                             AHI_GetAudioAttrs( AHI_INVALID_ID, actrl, AHIDB_MaxPlaySamples,(ULONG) &playsamples, TAG_DONE );
  3980.                                             AHI_ControlAudio( actrl, AHIC_MixFreq_Query, (ULONG) &mixfreq, TAG_DONE );
  3981.                                         
  3982.                                             buffersize = UDiv( UMult( playsamples,  id->Frequency ), mixfreq );
  3983.                                         
  3984.                                             if( buffersize < id->SampleLength )
  3985.                                             {
  3986.                                                 buffersize = id->SampleLength;
  3987.                                             }
  3988.                                             
  3989.                                             buffersize = UMult( buffersize, bytesPerPoint[ id->SampleType ] );
  3990.                                             
  3991.                                             if( buffer = AllocVec( buffersize*2, MEMF_PUBLIC|MEMF_CLEAR ) )
  3992.                                             {                                                
  3993.                                                 sample.ahisi_Address    = buffer;
  3994.                                                 
  3995.                                                 if( ! AHI_LoadSound( 0, AHIST_DYNAMICSAMPLE, &sample, actrl ) )
  3996.                                                 {
  3997.                                                     sample.ahisi_Address    = &buffer[ buffersize ];
  3998.                                                     
  3999.                                                     failed = (BOOL) AHI_LoadSound( 1, AHIST_DYNAMICSAMPLE, &sample, actrl );
  4000.                                                 }
  4001.                                                 
  4002.                                                 CopyMem( id->Sample, buffer, UMult( id->SampleLength, bytesPerPoint[ id->SampleType ] ) );
  4003.                                             }
  4004.                                             
  4005.                                         }
  4006.                                         else
  4007.                                         {
  4008.                                             sample.ahisi_Address    = id->Sample;
  4009.                                             
  4010.                                             failed = (BOOL) AHI_LoadSound( 0, AHIST_SAMPLE, &sample, actrl );
  4011.                                         }
  4012.                                         
  4013.                                         dbug( kprintf("child: loading sample\n"); )
  4014.                                         
  4015.                                         if( ! failed )
  4016.                                         {
  4017.                                             failed = TRUE;
  4018.                                             
  4019.                                             if( ! AHI_ControlAudio( actrl,
  4020.                                                 AHIC_Play, TRUE,
  4021.                                                 TAG_DONE ) )
  4022.                                             {
  4023.                                                 AHI_Play( actrl, 
  4024.                                                     AHIP_BeginChannel, 0,
  4025.                                                     AHIP_Freq, freq,
  4026.                                                     AHIP_Vol, vol,
  4027.                                                     AHIP_Pan, id->Panning,
  4028.                                                     AHIP_Sound, 0,
  4029.                                                     AHIP_EndChannel, NULL,
  4030.                                                     ( stereo ? TAG_IGNORE : TAG_END ), 0L,
  4031.                                                     AHIP_BeginChannel, 1,
  4032.                                                     AHIP_Freq, freq,
  4033.                                                     AHIP_Vol, vol,
  4034.                                                     AHIP_Pan, id->Panning,
  4035.                                                     AHIP_Sound, 0,
  4036.                                                     AHIP_EndChannel, NULL,
  4037.                                                     TAG_DONE );
  4038.                                                 
  4039.                                                 failed = FALSE;
  4040.                                                 
  4041.                                                 dbug( kprintf( "child: playback started, freq: %ld\n", freq ); )
  4042.                                             }
  4043.                                             else
  4044.                                             {
  4045.                                                 dbug( kprintf( "child: CtrlAudio failed\n" ); )
  4046.                                             }
  4047.                                         }
  4048.                                         else
  4049.                                         {
  4050.                                             dbug( kprintf( "child: loadsample failed\n" ); )
  4051.                                         }
  4052.                                     }
  4053.                                     else
  4054.                                     {
  4055.                                         dbug( kprintf( "child: AllocAudio failed\n"); )
  4056.                                     }
  4057.                                 }
  4058.                                 else
  4059.                                 {
  4060.                                     dbug( kprintf( "child: No free store\n" ); )
  4061.                                 }
  4062.                             }
  4063.                             
  4064.                             if( failed )
  4065.                             {
  4066.                                 AHI_FreeAudio( actrl );
  4067.                                 FreeVec( SoundHook );
  4068.                                 FreeVec( buffer );
  4069.                                 buffer = NULL;
  4070.                                 CloseAHI( AHImp, ahir );
  4071.                                 AHIBase = NULL;
  4072.                                 SetTDMode( cb, id, BUT_STOP );
  4073.                             }
  4074.                             else
  4075.                             {
  4076.                                 SetTDMode( cb, id, BUT_PLAY );
  4077.                             }
  4078.                         }
  4079.                         
  4080.                         // ReleaseSemaphore( &id->Lock );
  4081.                     break;
  4082.                 }
  4083.  
  4084.                 if( msg->Message.mn_ReplyPort )
  4085.                 {
  4086.                     ReplyMsg( &msg->Message );
  4087.                 }
  4088.                 else // NT_FREEMSG
  4089.                 {
  4090.                     FreeVec( msg );
  4091.                 }
  4092.             }
  4093.         }
  4094.         
  4095.         if( rcv & SIGBREAKF_CTRL_C )
  4096.         {
  4097.             dbug( kprintf( "child: end of sample\n" ); )
  4098.             
  4099.             if( AHIBase )
  4100.             {
  4101.                 ObtainSemaphoreShared( &id->Lock );
  4102.                 if( id->SignalTask && id->SignalBit != -1 )
  4103.                 {
  4104.                     Signal( id->SignalTask, 1L << id->SignalBit );
  4105.                 }
  4106.                 ReleaseSemaphore( &id->Lock );
  4107.             
  4108.                 if( ! id->Continuous )
  4109.                 {
  4110.                     AHI_FreeAudio( actrl );
  4111.                     FreeVec( SoundHook );
  4112.                     FreeVec( buffer );
  4113.                     buffer = NULL;
  4114.                     CloseAHI( AHImp, ahir );
  4115.                     AHIBase = NULL;
  4116.                     SetTDMode( cb, id, BUT_STOP );
  4117.                 }
  4118.             }
  4119.         }
  4120.     }
  4121.     
  4122. #ifndef __MAXON__
  4123. #define SysBase    cb->cb_SysBase
  4124. #endif
  4125. }
  4126.  
  4127. /****************************************************************************/
  4128.  
  4129. unsigned __regargs strlen( STRPTR str )
  4130. {
  4131.     STRPTR p = str;
  4132.     
  4133.     while( *str++ );
  4134.     
  4135.     return( ~(unsigned) (p - str) );
  4136. }
  4137.  
  4138. /****************************************************************************/
  4139.